Hogyan használhatunk shell parancsot, hogy csak az első oszlopot és az utolsó oszlopot jelenítsük meg egy szöveges fájlban?

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 a sponge 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 

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük