Némi segítségre van szükségem, hogy kiderítsem, hogyan használhatom a sed parancsot, hogy csak az első oszlopot és az utolsó oszlopot jelenítsem meg egy szöveges fájlban. Ez az, ami eddig az 1. oszlopnál volt:
cat logfile | sed "s/\|/ /"|awk "{print $1}"
Gyengén próbáltam elérni, hogy az utolsó oszlop is megjelenjen:
cat logfile | sed "s/\|/ /"|awk "{print $1}{print $8}"
Ez azonban az első oszlopot és az utolsó oszlopot veszi át, és egy listába egyesíti őket. Van-e mód arra, hogy az első és az utolsó oszlopokat egyértelműen kinyomtassák sed és awk parancsokkal?
Minta bevitele:
foo|dog|cat|mouse|lion|ox|tiger|bar
Megjegyzések
- Adjon meg néhány minta bevitelt.
Válasz
Majdnem ott van. Csak tegye egymás mellé mindkét oszlopreferenciát.
cat logfile | sed "s/|/ /" | awk "{print $1, $8}"
Ne feledje, hogy itt nem kell cat
.
sed "s/|/ /" logfile | awk "{print $1, $8}"
Megjegyezheti azt is, hogy awk
elmondhatja, hogy az oszlopelválasztók |
, üres helyek helyett, tehát nem kell sed
sem.
awk -F "|" "{print $1, $8}" logfile
javaslatok szerint Caleb szerint, ha olyan megoldást szeretne, amely még mindig az utolsó mezőt adja ki , még ha nincs is pontosan nyolc, használhatja a $NF
parancsot.
awk -F "|" "{print $1, $NF}" logfile
Ha azt szeretné, hogy kimenet a |
elválasztók megtartásához, szóköz helyett megadhatja a kimeneti mező elválasztóit. Sajnos ez “esetlenebb”, mint csak a -F
zászló használata, de itt három megközelítés található.
-
Hozzárendelheti a bemenetet és a kimeneti mezőelválasztókat magában
awk
, a BEGIN blokkban.awk "BEGIN {FS = OFS = "|"} {print $1, $8}" logfile
-
Ezeket a változókat akkor rendelheti hozzá, amikor a
awk
parancsot meghívja a parancssorból, a-v
zászlón keresztül.awk -v "FS=|" -v "OFS=|" "{print $1, $8}" logfile
-
vagy egyszerűen:
awk -F "|" "{print $1 "|" $8}" logfile
megjegyzések
- Jó feladat a probléma egyszerűsítésének lebontása. Megjegyzést fűzhet a
|
kimeneti elválasztóként történő használatához a kimeneti elválasztóként a az alapértelmezett hely a karaktersorozat összefűzéséhez. Azt is elmagyarázhatja, hogy a$NF
-t használja-e kemény kódolás helyett az$8
kódot az utolsó oszlop megszerzéséhez. - utána hogyan lehet frissíteni a fájlt?
- @pankajprasad Írjon egy új fájlba h
>
majd felülírja a régit, vagy használja asponge
parancsot. Ez valóban új kérdés. - @Sparhawk működik, de a tartalom visszaszerzése törlődik. hogyan kell ezt kezelni?
- @pankajprasad Új kérdést kell feltenned. Kattintson a tetején lévő nagy kék gombra, amely a következőt írja: ” Kérdés feltétele “.
Válasz
Egyébként a awk
-t használja:
awk "{ print $1, $NF }" file
Megjegyzések
- Nem lenne ‘ t meg kell adnia a beviteli mező elválasztóját (mivel ebben az esetben úgy tűnik, hogy
|
legyen inkább az a szóköz)-F\|
vagy hasonlóval? És mi lenne, ha ugyanazt a határolót akarná használni a kimenethez? - @Caleb Valószínűleg: arra vártam, hogy az OP megerősítse, hogy pontosan hogyan néz ki a bemenet, ahelyett, hogy megpróbálnám találgatás a nem működő példák alapján …
- Ne feledje, hogy ez feltételezi, hogy a bemenet legalább 2 mezőt tartalmaz.
- @St é phaneChazelas OP kódban egyértelműen kijelentette, hogy mindig nyolc mezője van.
- @ michaelb958 szerintem ” egyértelműen ” túlértékeli az esetet, csak egy kicsit 🙂
Válasz
Csak cserélje le az elsőtől az utolsóig |
|
(vagy szóközzel, ha úgy tetszik):
sed "s/|.*|/|/"
Ne feledje, hogy bár nincs sed
megvalósítás, ahol a |
speciális (mindaddig, amíg kiterjesztett rendszeres a kifejezések nincsenek engedélyezve a -E
vagy a egyes megvalósításokban), maga a \|
egyesekben különleges, például a GNU sed
. Tehát ne meneküljön |
, ha azt össze kívánja egyezni a |
karakterrel.
Ha szóközzel helyettesítjük, és ha a bemenet már tartalmazhat csak egy |
sorokat, akkor ezt külön kell kezelnie |.*|
nem fog mérkőzni ezeken.Ez lehet:
sed "s/|\(.*|\)\{0,1\}/ /"
(vagyis a .*|
részt választhatóvá teheti) vagy:
sed "s/|.*|/ /;s/|/ /"
vagy:
sed "s/\([^|]*\).*|/\1 /"
Ha az első és a nyolcadik mezőt szeretné, függetlenül a a bemenet, akkor ez csak:
cut -d"|" -f1,8
(mindezek bármilyen POSIX-kompatibilis segédprogrammal működnek, ha a bemenet érvényes szöveget alkot (különösen, a sed
fájlok általában nem fognak működni, ha a bemenetnek vannak bájtjai vagy bájtsorozatai, amelyek nem formálnak érvényes karaktereket az aktuális területi beállításokban, például: printf "unix|St\351phane|Chazelas\n" | sed "s/|.*|/|/"
UTF-8 területi beállításban)).
Válasz
Ha úgy találja, hogy ügyetlen és nyugtalan, akkor elérheti a ugyanaz a dolog a coreutils-szal:
paste <( cut -d"|" -f1 file) \ <(rev file | cut -d"|" -f1 | rev)
Megjegyzések
-
cut
tisztább és kompaktabb, mint az awk / sed, ha csak az első oszlop érdekel, vagy ha az elválasztók rögzítettek (azaz nem változó számú szóköz). - Elég elegáns!
Válasz
Úgy tűnik, hogy megpróbálja megszerezni az első és utolsó szövegmezőt, amelyet a |
.
Feltételeztem, hogy a naplófájlod tartalmazza az alábbi szöveget,
foo|dog|cat|mouse|lion|ox|tiger|bar bar|dog|cat|mouse|lion|ox|tiger|foo
a kimenet, például:
foo bar bar foo
Ha igen, akkor itt jön a parancs a “s”
A GNU sed segítségével,
sed -r "s~^([^|]*).*\|(.*)$~\1 \2~" file
Példa:
$ echo "foo|dog|cat|mouse|lion|ox|tiger|bar" | sed -r "s~^([^|]*).*\|(.*)$~\1 \2~" foo bar
megjegyzések
- Az oszlopokat nem határolja egy cső | de oszlopokban vannak, érdekel a sed használata, de nem az awk parancs használata, mint a parancsában: sed -r ‘ s ~ ^ ([^ |] *) . * \ | (. *) $ ~ \ 1 \ 2 ~ ‘ fájl
- ” Az oszlopok nem pipa határolja | de vannak ” oszlopokban, az oszlopokat szóközök választják el egymástól?
- A minta bemenet és a kimenet jobb lenne.
Válasz
Valószínűleg a sed
címmel kell megtenni – egyébként is tenném -, de csak mert ezt még senki sem írta:
while IFS=\| read col1 cols do printf %10s%-s\\n "$col1 |" " ${cols##*|}" done <<\INPUT foo|dog|cat|mouse|lion|ox|tiger|bar INPUT
OUTPUT
foo | bar