Sådan slettes den sidste kolonne i en fil i Linux

Jeg vil slette den sidste kolonne i en txt-fil, mens jeg ikke ved, hvad kolonnenummeret er. Hvordan kunne jeg gøre dette?

Eksempel:

Input:

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

Og jeg ønsker, at min output skal være :

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

Kommentarer

  • Der er mange måder at gøre dette på. venligst tilføj et eksempel og dit forventede output fra det ..
  • @heemayl ok det gjorde jeg
  • Tak..er kolonnefanen adskilt eller mellemrumsskilt?
  • @heemayl space is deliminator
  • cut lyder som værktøjet til jobbet.

Svar

Med awk:

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

eller:

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

eller:

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

Selvom dette ligner voodoo, fungerer det. Der er tre dele til hver af disse awk-kommandoer.

Den første er NF, hvilket er en forudsætning for den anden del. NF er en variabel, der indeholder antallet af felter i en linje. I AWK er tingene sandt, hvis de “ikke er 0 eller tom streng "". Derfor er den anden del (hvor NF reduceres) sker kun, hvis NF ikke er 0.

Den anden del (enten NF-=1 NF-- eller --NF) trækker bare en fra variablen NF. Dette forhindrer det sidste felt i at blive udskrevet, for når du ændrer et felt (fjerner det sidste felt i dette tilfælde), awk re-konstruerer $0, sammenkæder alle felter adskilt af mellemrum som standard . $0 indeholdt ikke det sidste felt længere.

Den sidste del er 1. Det er ikke magisk, det bruges bare som et udtryk, der betyder true. Hvis et awk -udtryk evalueres til sandt uden nogen tilknyttet handling, er awk standardhandling print $0 .

Kommentarer

  • @JJoao: Ah, tak, glemte --. En note, i øjeblikket skal du have ;1 til POSIX-kompatibel.
  • Mit første instinkt ville være at bruge en for-loop, men dette er meget mere kortfattet og klogt.
  • Det er ' værd at bemærke, at hvis du ' bruger en ikke-standardafgrænser, skal du ' Jeg skal foretage nogle ændringer. Under forudsætning af at , er din afgrænser: awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
  • Effekten af dekrementering af NF er udefineret adfærd fra POSIX – du får forskellig output afhængigt af, hvilket awk du ' kører igen. Nogle awks fjerner det sidste felt, som du vil, andre vil slet ikke gøre noget, og andre kan rapportere en syntaksfejl eller noget andet.

Svar

Brug af grep med PCRE:

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

Brug af GNU sed:

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

Kommentarer

  • @ramin Sikker. .Kan du spørge det som et nyt spørgsmål (sådan fungerer dette site) 🙂
  • @ramin Giver det dig noget tidsbegrænsning eller nogen advarsel?
  • der står, at dette ikke er standardspørgsmål!
  • @ramin Ok.. Lad mig kontakte en administrator, måske kan de hjælpe dig med det .. btw har du tjekket en gammel QA vedrørende dit spørgsmål? det er en mulighed for, at spørgsmålet allerede er stillet og besvaret ..
  • Don ' t stille super grundlæggende spørgsmål som " hvordan kan jeg omdøbe et filnavn i Linux ". Brug Google.

Svar

Brug af Perl:

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

Brug af rev + cut:

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

Svar

Brug af GNU sed:

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

Mere generelt er denne fungerer med BSD sed i OSX samt GNU sed:

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

Svar

Hvis afgrænseren altid er en enkelt tegn (så to eller flere på hinanden følgende afgrænsere angiver tomme felter), kan du head bare den første linje fra din inputfil, tæl afgrænserne ( n afgrænsere betyder, at antallet af felter er n+1) brug derefter cut til at udskrive fra 1 st felt op til n th felt (næstsidste), f.eks. med tabulatorafgrænset input:

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

eller f.eks.med en csv fil:

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

Jeg kører nogle benchmarks senere, hvis jeg har tid, men med enorme input tror jeg dette løsningen skal være hurtigere end andre løsninger, der bruger regex, da denne udfører minimal behandling på første linje for at få antallet af felter og derefter bruger cut, som er optimeret til dette job.

Svar

Bærbart kan du bruge en af disse:

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

Svar

Brug af vim:

Åbn fil i vim

vim <filename> 

Gå til første række, bare hvis markøren er placeret et andet sted.

gg 

Opret en makro med navnet “q” qq, der går bag på den aktuelle linje $, og går derefter tilbage til det sidste mellemrum F (kapital F, efterfulgt af bogstavelig MELLEMRUM) slet derefter fra nuværende position til slutningen af linjen D gå ned til næste linje j og stop makrooptagelse med q.

qq$F Djq 

Nu kan vi gentage vores makro med @q for hver linje.
Vi kan også trykke på @@ for at gentage den sidste makro eller endnu lettere:

99@q 

for at gentage makroen 99 gange.
Bemærk: Nummeret må ikke ligefrem matche linjerne.

Svar

For folk, der har et lignende problem, men med forskellige feltadskillere, er dette awk metode bevarer feltudskilleren korrekt:

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

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *