Potřebuji pomoc, abych zjistil, jak pomocí příkazu sed zobrazit pouze první sloupec a poslední sloupec v textovém souboru. Tady je to, co zatím pro sloupec 1:
cat logfile | sed "s/\|/ /"|awk "{print $1}"
Můj slabý pokus o zobrazení posledního sloupce byl také:
cat logfile | sed "s/\|/ /"|awk "{print $1}{print $8}"
Toto však vezme první a poslední sloupec a sloučí je do jednoho seznamu. Existuje způsob, jak jasně vytisknout první sloupec a poslední sloupce pomocí příkazů sed a awk?
Ukázkový vstup:
foo|dog|cat|mouse|lion|ox|tiger|bar
Komentáře
- Uveďte prosím ukázkový vstup.
Odpověď
Téměř tam. Stačí dát oba odkazy na sloupce vedle sebe.
cat logfile | sed "s/|/ /" | awk "{print $1, $8}"
Upozorňujeme, že zde cat nepotřebujete .
sed "s/|/ /" logfile | awk "{print $1, $8}"
Upozorňujeme, že awk je oddělovač sloupců | místo mezer, takže nepotřebujete sed.
awk -F "|" "{print $1, $8}" logfile
Podle návrhů autorů Caleb , pokud chcete řešení, které stále zobrazuje poslední pole , i když jich není přesně osm, můžete použít $NF.
awk -F "|" "{print $1, $NF}" logfile
Také pokud chcete výstup, aby se zachovaly oddělovače |, místo mezery můžete zadat oddělovače výstupního pole. Bohužel je to trochu neohrabanější než pouhé použití příznaku -F, ale zde jsou tři přístupy.
-
Můžete přiřadit vstup a oddělovače výstupních polí v
awksamotném v BEGIN bloku.awk "BEGIN {FS = OFS = "|"} {print $1, $8}" logfile -
Tyto proměnné můžete přiřadit při volání
awkz příkazového řádku pomocí příznaku-v.awk -v "FS=|" -v "OFS=|" "{print $1, $8}" logfile -
nebo jednoduše:
awk -F "|" "{print $1 "|" $8}" logfile
Komentáře
- Dobrá práce, jak se tento problém dá zjednodušit. Můžete přidat poznámku o tom, jak použít
|jako oddělovač výstupu místo výchozí prostor pro zřetězení řetězců. Můžete také vysvětlit, že k získání posledního sloupce použijte místo pevného kódování$NF$8. - poté, jak aktualizovat soubor?
- @pankajprasad Napsat do nového souboru vtip h
>poté přepsat starý nebo použítsponge. Toto je opravdu nová otázka. - @Sparhawk to funguje, ale vystružování obsahu je vymazáno. jak se s tím vypořádat?
- @pankajprasad Musíte se zeptat na novou otázku. Klikněte na velké modré tlačítko nahoře s nápisem “ Položit otázku „.
Odpověď
Každopádně používáte awk:
awk "{ print $1, $NF }" file
Komentáře
- Nebylo by nutné ‚ zadat oddělovač vstupního pole (protože v tomto případě se zdá, že být
|spíše tímto prostorem) s-F\|nebo podobným? Také co kdyby chtěl použít stejný oddělovač pro výstup? - @Caleb Pravděpodobně: Čekal jsem, až OP potvrdí, jak přesně vypadal vstup, místo aby se snažil hádejte na základě nepracujících příkladů …
- Všimněte si, že předpokládáme, že vstup obsahuje alespoň 2 pole.
- @St é phaneChazelas OP jasně uvedl v kódu, že má vždy osm polí.
- @ michaelb958 Myslím, že “ jasně “ nadhodnocuje případ, jen trochu 🙂
Odpovědět
Stačí nahradit z prvního na poslední | s | (případně mezerou):
sed "s/|.*|/|/"
Všimněte si, že ačkoli neexistuje žádná sed implementace, kde je | zvláštní (pokud je rozšířeno pravidelné výrazy nejsou povoleny prostřednictvím -E nebo v některých implementacích), \| je sám o sobě speciální v některých jako GNU sed. Měli byste tedy ne uniknout |, pokud chcete, aby odpovídal znaku |.
Pokud nahradíte mezerou a pokud vstup již může obsahovat řádky pouze s jedním |, budete s tím muset zacházet zvlášť jako |.*| na nich nebude odpovídat.Může to být:
sed "s/|\(.*|\)\{0,1\}/ /"
(to znamená, že je .*| volitelná) Nebo:
sed "s/|.*|/ /;s/|/ /"
nebo:
sed "s/\([^|]*\).*|/\1 /"
Pokud chcete první a osmé pole bez ohledu na počet polí v vstup, pak je to jen:
cut -d"|" -f1,8
(všechny by za předpokladu vstupu fungovaly s jakýmkoli nástrojem kompatibilním s POSIXem) tvoří platný text (zejména sed obvykle nebudou fungovat, pokud má vstup bajty nebo sekvence bajtů, které nevytvářejí platné znaky v aktuálním národním prostředí, jako například printf "unix|St\351phane|Chazelas\n" | sed "s/|.*|/|/" v národním prostředí UTF-8)).
Odpověď
Pokud se ocitnete v nepořádku a bez sedu, můžete dosáhnout totéž s coreutils:
paste <( cut -d"|" -f1 file) \ <(rev file | cut -d"|" -f1 | rev)
Komentáře
-
cutje čistší a kompaktnější než awk / sed, když vás zajímá pouze první sloupec, nebo pokud jsou pevně nastaveny oddělovače (tj. ne variabilní počet mezer). - Docela elegantní!
Odpověď
Vypadá to, že se pokoušíte získat první a poslední pole textu, která jsou ohraničena |.
Předpokládal jsem, že váš soubor protokolu obsahuje následující text,
foo|dog|cat|mouse|lion|ox|tiger|bar bar|dog|cat|mouse|lion|ox|tiger|foo
A chcete výstup jako,
foo bar bar foo
Pokud ano, pak přichází příkaz pro vaše „s
Prostřednictvím GNU sed,
sed -r "s~^([^|]*).*\|(.*)$~\1 \2~" file
Příklad:
$ echo "foo|dog|cat|mouse|lion|ox|tiger|bar" | sed -r "s~^([^|]*).*\|(.*)$~\1 \2~" foo bar
Komentáře
- Sloupce nejsou ohraničeny rourou | ale jsou ve sloupcích, zajímá mě použití sed, ale nepoužívám příkaz awk, jako jste to udělali ve svém příkazu: sed -r ‚ s ~ ^ ([^ |] *) . * \ | (. *) $ ~ \ 1 \ 2 ~ ‚ soubor
- “ Sloupce jsou není ohraničen rourou | ale jsou ve sloupcích „, máte na mysli sloupce oddělené mezerami?
- Ukázkový vstup a výstup by byly lepší.
Odpověď
Pravděpodobně byste to měli udělat s sed – stejně bych – ale jen protože tento ještě nikdo nenapsal:
while IFS=\| read col1 cols do printf %10s%-s\\n "$col1 |" " ${cols##*|}" done <<\INPUT foo|dog|cat|mouse|lion|ox|tiger|bar INPUT
VÝSTUP
foo | bar