Cum se folosește o comandă shell pentru a afișa prima coloană și ultima coloană dintr-un fișier text?

Am nevoie de ajutor pentru a afla cum să folosesc comanda sed pentru a afișa doar prima coloană și ultima coloană într-un fișier text. Iată ce am până acum pentru coloana 1:

cat logfile | sed "s/\|/ /"|awk "{print $1}" 

Încercarea mea slabă de a afișa și ultima coloană a fost:

cat logfile | sed "s/\|/ /"|awk "{print $1}{print $8}" 

Cu toate acestea, aceasta ia prima coloană și ultima coloană și le îmbină într-o listă. Există o modalitate de a imprima prima coloană și ultimele coloane în mod clar cu comenzi sed și awk?

Introducere eșantion:

foo|dog|cat|mouse|lion|ox|tiger|bar 

Comentarii

  • Vă rugăm să furnizați câteva exemple de intrare.

Răspuns

Aproape acolo. Pur și simplu puneți ambele referințe de coloană una lângă cealaltă.

cat logfile | sed "s/|/ /" | awk "{print $1, $8}" 

Rețineți, de asemenea, că nu aveți nevoie de cat aici .

sed "s/|/ /" logfile | awk "{print $1, $8}" 

De asemenea, rețineți că puteți spune awk că separatoarele de coloane sunt |, în loc de spații goale, deci nu aveți nevoie de sed.

awk -F "|" "{print $1, $8}" logfile 

Conform sugestii de Caleb , dacă doriți o soluție care să afișeze în continuare ultimul câmp , chiar dacă nu sunt exact opt, puteți utiliza $NF.

awk -F "|" "{print $1, $NF}" logfile 

De asemenea, dacă doriți ieșire pentru a păstra separatorii |, în loc să folosiți un spațiu, puteți specifica separatorii câmpului de ieșire. Din păcate, este „puțin mai neîndemânatic decât să folosești semnalizatorul -F, dar iată trei abordări.

  • Puteți atribui intrarea și separatoare de câmpuri de ieșire în awk în sine, în blocul BEGIN.

    awk "BEGIN {FS = OFS = "|"} {print $1, $8}" logfile 
  • Puteți atribui aceste variabile atunci când apelați awk din linia de comandă, prin semnalizatorul -v.

    awk -v "FS=|" -v "OFS=|" "{print $1, $8}" logfile 
  • sau pur și simplu:

    awk -F "|" "{print $1 "|" $8}" logfile 

Comentarii

  • Slujbă bună care descrie modul în care această problemă poate fi simplificată. Puteți adăuga o notă despre cum să utilizați | ca separator de ieșire în loc de spațiul implicit pentru concatenarea șirurilor. De asemenea, puteți explica utilizarea $NF în loc de codare dură $8 pentru a obține ultima coloană.
  • după aceea cum să actualizați fișierul?
  • @pankajprasad Scrieți într-un nou fișier h > apoi suprascrieți-o pe cea veche sau utilizați sponge. Aceasta este într-adevăr o întrebare nouă.
  • @Sparhawk funcționează, dar alezarea conținutului este ștearsă. cum să rezolvați problema?
  • @pankajprasad Trebuie să puneți o nouă întrebare. Faceți clic pe butonul albastru mare din partea de sus, pe care scrie ” Puneți întrebarea „.

Răspuns

Utilizați oricum awk:

awk "{ print $1, $NF }" file 

Comentarii

  • Nu ar trebui să ‘ nu trebuie să specificați separatorul de câmp de intrare (deoarece în acest caz se pare că fi | mai degrabă acel spațiu) cu -F\| sau similar? Și dacă ar dori să folosească același delimitator pentru ieșire?
  • @Caleb Probabil: așteptam ca OP să confirme cum arăta exact intrarea, mai degrabă decât să încerc să ghici pe baza exemplelor care nu funcționează …
  • Rețineți că asta presupune că intrarea conține cel puțin 2 câmpuri.
  • @St é phaneChazelas OP a declarat clar în cod că are opt câmpuri, întotdeauna.
  • @ michaelb958 Cred că ” clar ” supraestimează cazul, doar puțin 🙂

Răspunde

Doar înlocuiește de la primul la ultimul | cu un | (sau spațiu dacă preferați):

sed "s/|.*|/|/" 

Rețineți că, deși nu există nicio sed implementare în care | este special (atâta timp cât extins regulat expresiile nu sunt activate prin -E sau în unele implementări), \| în sine este special în unele ca GNU sed. Deci, nu trebuie să scapi de | dacă intenționezi să se potrivească cu caracterul |.

Dacă înlocuiți cu spațiu și dacă intrarea poate conține deja linii cu un singur |, atunci va trebui să tratați acest lucru special ca |.*| nu a câștigat meciul pe acelea.Acesta ar putea fi:

sed "s/|\(.*|\)\{0,1\}/ /" 

(adică faceți .*| opțional) Sau:

sed "s/|.*|/ /;s/|/ /" 

sau:

sed "s/\([^|]*\).*|/\1 /" 

Dacă doriți primul și al optulea câmp, indiferent de numărul de câmpuri din intrarea, atunci este doar:

cut -d"|" -f1,8 

(toate acestea ar funcționa cu orice utilitar compatibil POSIX presupunând intrarea formează un text valid (în special, cele sed nu vor funcționa în general dacă intrarea are octeți sau secvențe de octeți care nu formează caractere valide în localitatea curentă, cum ar fi printf "unix|St\351phane|Chazelas\n" | sed "s/|.*|/|/" într-o localizare UTF-8)).

Răspundeți

Dacă vă simțiți mai puțin stângaci și mai puțin sed, puteți atinge același lucru cu coreutils:

paste <( cut -d"|" -f1 file) \ <(rev file | cut -d"|" -f1 | rev) 

Comentarii

  • cut este mai curat și mai compact decât awk / sed când sunteți doar interesat de prima coloană sau dacă delimitările sunt fixe (adică nu un număr variabil de spații).
  • Destul de elegant!

Răspuns

Se pare că încercați să obțineți primul și ultimul câmp de text delimitat de |.

Am presupus că fișierul jurnal conține textul ca mai jos,

foo|dog|cat|mouse|lion|ox|tiger|bar bar|dog|cat|mouse|lion|ox|tiger|foo 

Și doriți ieșirea ca,

foo bar bar foo 

Dacă da, atunci vine comanda pentru „s

Prin GNU sed,

sed -r "s~^([^|]*).*\|(.*)$~\1 \2~" file 

Exemplu:

$ echo "foo|dog|cat|mouse|lion|ox|tiger|bar" | sed -r "s~^([^|]*).*\|(.*)$~\1 \2~" foo bar 

Comentarii

  • Coloanele nu sunt delimitate de o conductă | dar sunt în coloane, sunt interesat să folosesc sed, dar să nu folosesc comanda awk așa cum ați făcut-o în comanda dvs.: sed -r ‘ s ~ ^ ([^ |] *) . * \ | (. *) $ ~ \ 1 \ 2 ~ ‘ fișier
  • ” Coloanele sunt nedelimitat de o conductă | dar sunt în coloane „, vrei să spui că coloanele sunt separate prin spații?
  • Un exemplu de intrare și o ieșire ar fi mai bune.

Răspuns

Probabil că ar trebui să o faceți cu sed – aș face oricum – dar, doar pentru că nimeni nu l-a scris încă:

while IFS=\| read col1 cols do printf %10s%-s\\n "$col1 |" " ${cols##*|}" done <<\INPUT foo|dog|cat|mouse|lion|ox|tiger|bar INPUT 

IEȘIRE

 foo | bar 

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *