Cum se șterge ultima coloană a unui fișier în Linux

Vreau să șterg ultima coloană a unui fișier txt, în timp ce nu știu care este numărul coloanei este. Cum aș putea face acest lucru?

Exemplu:

Intrare:

1223 1234 1323 ... 2222 123 1233 1234 1233 ... 3444 125 0000 5553 3455 ... 2334 222 

Și vreau ca ieșirea mea să fie :

1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334 

Comentarii

  • Există multe modalități de a face acest lucru .. vă rugăm să adăugați un exemplu și ieșirea dvs. așteptată din acesta ..
  • @heemayl ok am făcut-o
  • Mulțumesc..sunt tabul coloanelor separat sau spațiul separat?
  • Spațiul @heemayl este deliminator
  • cut sună ca instrumentul pentru job.

Răspuns

Cu awk:

awk "NF{NF-=1};1" <in >out 

sau:

awk "NF{NF--};1" <in >out 

sau:

awk "NF{--NF};1" <in >out 

Deși acest lucru arată ca voodoo, funcționează. Există trei părți pentru fiecare dintre aceste comenzi awk.

Prima este NF, care este o condiție prealabilă pentru a doua parte. NF este o variabilă care conține numărul de câmpuri dintr-o linie. În AWK, lucrurile sunt adevărate dacă „nu sunt 0 sau șirul gol "". Prin urmare, a doua parte (unde NF este decrementată) se întâmplă numai dacă NF nu este 0.

A doua parte (fie NF-=1 NF-- sau --NF) scade doar una din variabila NF. Aceasta împiedică tipărirea ultimului câmp, deoarece atunci când schimbi un câmp (eliminând ultimul câmp în acest caz), awk reconstruiește $0, concatenează toate câmpurile separate de spațiu în mod implicit . $0 nu mai conținea ultimul câmp.

Partea finală este 1. „Nu este magic, este doar folosit ca o expresie care înseamnă true. Dacă o expresie awk se evaluează la adevărat fără nicio acțiune asociată, awk acțiune implicită este print $0 .

Comentarii

  • @JJoao: Ah, mulțumesc, am uitat de --. O notă, în prezent, aveți nevoie de ;1 pentru compatibilitatea POSIX.
  • Instinctul meu inițial ar fi să folosesc o buclă for, dar aceasta este mult mai concisă și mai inteligentă.
  • Merită menționat ' că, dacă ' utilizați un delimitator non-implicit, ' va trebui să facă unele modificări. Presupunând că , este delimitatorul dvs.: awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
  • Efectul decrementării NF este un comportament nedefinit de POSIX – veți obține ieșire diferită în funcție de starea pe care o executați '. Unele awks vor elimina ultimul câmp după cum doriți, altele nu vor face deloc, iar altele ar putea raporta o eroare de sintaxă sau orice altceva.

Răspuns

Utilizarea grep cu PCRE:

$ grep -Po ".*(?=\s+[^\s]+$)" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334 

Utilizarea GNU sed:

$ sed -r "s/(.*)\s+[^\s]+$/\1/" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334 

Comentarii

  • @ramin Sigur. .ar puteai să o întrebați ca o nouă întrebare (așa funcționează acest site) 🙂
  • @ramin Vă oferă ceva restricție de timp sau vreun avertisment?
  • se spune că nu este o întrebare standard!
  • @ramin Ok .. permiteți-mi să contactez un administrator, poate că te pot ajuta cu asta .. ați verificat vreun QA vechi cu privire la întrebarea dvs.? este o posibilitate ca întrebarea să fie deja pusă și răspunsă.
  • Nu ' nu puneți întrebări super de bază precum " cum pot redenumi un nume de fișier în Linux ". Utilizați Google.

Răspuns

Utilizarea Perl:

perl -lane "$,=" ";pop(@F);print(@F)" in 

Utilizarea rev + cut:

rev in | cut -d " " -f 2- | rev 

Răspuns

Utilizarea sed GNU:

sed -r "s/\s+\S+$//" input.txt 

Mai general, acesta funcționează cu BSD sed în OSX, precum și cu GNU sed:

sed "s/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//" input.txt 

Răspuns

Dacă delimitatorul este întotdeauna un singur caracter (deci doi sau mai mulți delimitatori consecutivi desemnează câmpuri goale), puteți head doar prima linie din fișierul de intrare, numărați delimitatorii ( n delimitatori înseamnă că numărul de câmpuri este n+1), apoi utilizați cut pentru a imprima din 1 st câmp până la n th câmp (de la al doilea la ultimul), de ex. cu intrare delimitată de tab-uri:

n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l) cut -f1-$n infile > outfile 

sau de ex.cu un fișier csv :

n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l) cut -d, -f1-$n infile > outfile 

Voi rula câteva repere mai târziu dacă am timp, dar cu o intrare imensă cred că acest lucru soluția ar trebui să fie mai rapidă decât alte soluții care utilizează regex, deoarece aceasta face o procesare minimă pe prima linie pentru a obține numărul câmpurilor și apoi folosește cut, care este optimizat pentru acest job. / p>

Răspuns

Portabil, puteți utiliza oricare dintre acestea:

sed "s/[[:space:]]*[^[:space:]]*$//" file awk "{sub(/[[:space:]]*[^[:space:]]*$/,"")}1" file 

Răspuns

Folosind vim:

Deschideți fișierul în vim

vim <filename> 

Mergeți la primul rând, doar în cazul în care cursorul este plasat în altă parte.

gg 

Creați o macro numită „q” qq, care merge în spatele liniei curente $, apoi revine la ultimul spațiu F (F majusculă, urmată de spațiu literal) apoi ștergeți din poziția curentă până la sfârșitul liniei D mergeți la linia următoare j și opriți înregistrarea macro cu q.

qq$F Djq 

Acum putem repeta macro-ul nostru cu @q pentru fiecare linie.
Putem apăsa și @@ pentru a repeta ultima macrocomandă sau chiar mai ușor:

99@q 

pentru a repeta macrocomanda de 99 de ori.
Notă: numărul nu trebuie să se potrivească exact cu liniile.

Răspuns

Pentru persoanele care au o problemă similară, dar cu separatori de câmp diferiți, acest awk va păstra corect separatorul de câmp:

$ cat file foo.bar.baz baz.bar.foo $ awk -F"." "sub(FS $NF,x)" file foo.bar baz.bar 

Lasă un răspuns

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