Come posso eliminare la quinta parola di ogni riga di un file?


13

Voglio eliminare la quinta parola di ogni riga in un file.

Il contenuto corrente del file:

File is not updated or and will be removed  
System will shut down f within 10 seconds  
Please save your work 55 or copy to other location  
Kindly cooperate with us D  

Uscita prevista:

File is not updated and will be removed  
System will shut down within 10 seconds  
Please save your work or copy to other location  
Kindly cooperate with us

Risposte:


31

Che ne dici di cut:

$ cut -d' ' -f1-4,6- file.txt 
File is not updated and will be removed  
System will shut down within 10 seconds  
Please save your work or copy to other location  
Kindly cooperate with us
  • -d' ' imposta il delimitatore come spazio

  • -f1-4,6- seleziona dal primo al quarto campo (parola), lasciando il quinto e quindi continua a stampare dal 6 ° al resto.


11

Una soluzione con cut:

cut -d ' ' -f1-4 -f6- FILE

Il multiplo -fnon è supportato nel mio cut(GNU) almeno ..
heemayl

Supportato nel taglio BSD ma mi piace la tua risposta meglio della mia.
f0,

1
Se si tratta di GNU taglio, si ottiene la --complementbandiera per semplificare le cose: cut --complement -d ' ' -f5. Ricorda di reindirizzare l'output su un nuovo file, quindi mvsull'originale.
Toby Speight,

6

awk: rimuove il 5 ° campo

awk '{for (i=5; i<NF; i++) $i = $(i+1); NF--};1' file

Se si desidera salvare il file sul posto: /programming//q/16529716/7552

Potresti semplicemente cancellare il contenuto del 5 ° campo, ma ciò lascia 2 separatori di campi di output consecutivi:

awk '{$5 = ""};1' file

l'avvertenza qui è che la modifica del valore di qualsiasi campo in awk ha l'effetto collaterale di riscrivere l'intero "$ 0" con solo 1 separatore tra ciascun campo. dovrebbe essere preso in considerazione se si desidera mantenere qualsiasi allineamento (a meno che gnu awk non abbia un'opzione per evitarlo? awk / nawk regolare calcolerà $ 0)
Olivier Dulac

In entrambi i casi, riformattare la linea con un singolo separatore. Se in un separatore sono presenti 2 spazio o spazio + scheda, il risultato è un singolo spazio in atto. Questo è hoppefully OK per la maggior parte del testo.
NeronLeVelu,

4

Con POSIX sed:

sed -e 's/[^[:alnum:]_][[:alnum:]_][[:alnum:]_]*//4' <file

perché limitare la classe a: alnum: _ e non qualcos'altro allora :blank:o :space:?
NeronLeVelu,

@NeronLeVelu: dipende da come definisci ciò che crea una parola.
cuonglm

@mikeserv; Bella presa! Ho aggiornato la mia risposta.
cuonglm,

A cosa \(serve il gruppo di acquisizione \)?
Mikeserv,

@mikeserv: il mio errore di battitura, ho appena provato alcuni modi per conservare il delimitatore.
cuonglm,

2

glenn ha offerto una soluzione equivalente

awk '{$ 5 = ""; stampare}' di file

Come lui e altri hanno sottolineato, questo

  1. striscia gli spazi bianchi iniziali e finali di ogni riga,
  2. comprime ogni stringa di spazi bianchi (spazi e / o tabulazioni) in un singolo spazio e
  3. lascia due spazi tra la quarta e le sei parole.

Un trucco per risolvere il terzo problema è

awk '{$ 5 = ""; print} ' file | sed 's / / /'

Ciò lascerà comunque uno o più spazi aggiunti alla fine di qualsiasi riga in cui sono state inserite cinque o meno parole. Se riesci a identificare una parola che non verrà mai visualizzata nell'input,

awk '{$ 5 = "unicorno"; print} ' file | sed 's / * unicorn //'

gestirà anche quello (ma lascia ancora i problemi 1 e 2).


2
 sed 's/^\(\([[:blank:]]*[^[:blank:]]\{1,\}\)\{4\}\)[[:blank:]]*[^[:blank:]]*/\1/' YourFile > Output.txt
  • posix sed basato sul separatore spazio / tabulazione (meta class [: blank:]])
  • mantenere lo spazio seguente dopo la quinta parola ma rimuovendo quella precedente

Un modello più robusto (sed prende il modello più lungo possibile e il modello con *potrebbe mancare la separazione o la parola nella prima versione) ma una versione un po 'più lunga

sed 's/^\([[:blank:]]*\([^[:blank:]]\{1,\}[[:blank:]]\{1,\}\)\{4\}\[^[:blank:]]\{1,\}/\1/' YourFile > Output.txt

1
sed 's/[^[:blank:]]*//5'
Mikeserv,

@mikeserv, questo manterrà entrambi i separatori circostanti, sed 's/[[:blank:]*[^[:blank:]]*//5'è meglio. Ottimo punto Sospettavo che sed prendesse ogni singolo carattere come entità, ma prende il più grande schema non
frazionato

sed 's/[[:blank:]][^[:blank:]]*//4'rimuoverà completamente il 5 ° campo.
Mikeserv,

@mikeserv Supponendo che non ci sia spazio iniziale sulla linea (come nel campione)
NeronLeVelu

In questo caso, sì, penso che tu abbia ragione. Di solito una cosa del genere sarebbe un campo nullo e il comportamento sarebbe corretto. In questo caso si dovrebbe fare come ha fatto @cuonglm e garantire si fa riferimento a una parola ogni volta come sed 's/[[:blank:]][^[:blank:]][^[:blank:]]*//4', o, w / GNU / BSD / Toybox seds: sed -E 's/[[:blank:]][^[:blank:]]+//4'.
Mikeserv,

1

Perl.

perl -ne 'print $_ =~ /^(\w+ +\w+ +\w+ +\w+ +)\w+ (.*)/,"\n"' file

1

Un'altra possibilità, supponendo che GNU abbia tagliato:

cut -d' ' -f5 --complement file.txt

-1

Utilizzo di Perl> 5.10 (e uscita corretta di tutte le righe: 0)): -

perl -nE '/^((\w+ +){4})\w+ *(.*)/; say $1.$3' file
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.