Rimuovi le linee che non iniziano con un motivo da un determinato set di motivi


10

Ho un file che contiene dati come questo:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc

.. --.

Domanda: desidero rimuovere qualsiasi riga che non inizia con le seguenti stringhe:

report  
-th  
-to

ciò significa che l'output desiderato rimuoverà tutti quei punti e hash indesiderati medi e avrà questo aspetto:

report aaaaaaaa  
-th bbbbbbbbb  
-to ccccccccc

sed/ awk/ grep/ etc qualsiasi soluzione che funzionerà.

Risposte:


15

Utilizzo sedper modificare il file in atto:

sed -i '/^\(report\|-t\(h\|o\)\)/!d' your_file

Questo indica seddi eliminare tutte le linee che non corrispondono al modello. Il modello stesso è ^(inizio della linea), seguito da reporto -tseguito da ho o.

Si noti che questa non è una vera modifica sul posto: sedcrea una copia di backup temporanea e sovrascrive il file originale con esso.

Se vuoi sedconservare una copia di backup del file originale (che potrebbe essere una buona idea se il file contiene dati critici), dai allo -iswitch un'estensione per creare un file di backup:

sed -i'.bak' -e '/^\(report\|-t\(h\|o\)\)/!d' your_file

modificherà your_filee creerà un backup dell'originale chiamato your_file.bak.

Una nota a margine

Per favore, non fraintendete le mie intenzioni o offendetevi a questo, ma ho notato che avete molte domande simili relative a regex / elaborazione del testo. Vi consiglio di iniziare ad imparare sed, awke grepsul proprio per velocità di aiuto la vostra produttività. Ancora una volta, non fraintendetemi, sono troppo felice di aiutarvi (come lo sono la maggior parte delle persone qui intorno); è solo che penso che trarrai enormi benefici dalla raccolta di questi strumenti per il tuo uso quotidiano.

Solo per dimostrare quanto sono utili le persone qui intorno, considera il suggerimento di @ slm nei commenti qui sotto e sentiti libero di passare da questa chat in qualsiasi momento per domande.


1
La tua espressione regolare sembra inutilmente criptica. Penso che in realtà usi più personaggi che se avessi elencato esplicitamente le tre opzioni.
nispio,

1
@nispio Lo so, ma è probabile che sia più efficiente se il file in questione è di grandi dimensioni.
Joseph R.,

Interessante. Ho sempre misurato regexps in termini di lunghezza o leggibilità. Non ho mai pensato molto alla velocità di esecuzione. Non credo di sapere abbastanza su come vengono valutati per giudicare ciò che è veloce, ma presumo che sia anche specifico per l'implementazione, giusto?
nispio,

3
Ribadendo ciò che Joseph ha detto di essere disposto ad aiutare, se hai domande generali che non rientrano nello stile di domande e risposte, puoi sempre provare a chattare nella chat room di questo sito. chat.stackexchange.com/rooms/26/unix-and-linux . Molti di noi vivono lì, Cool
slm

@slm Grazie per questo. Lo aggiungerò alla mia risposta.
Joseph R.,


2

Utilizzando sed:

sed -n -e '/^report\|^-th\|^-to/p' filename

Non è un grande risparmio, ma potresti combinare il -th/ -toin -t[ho].
Kevin,

1
@Kevin È vero. Vedi la mia conversazione con Joseph R. nei commenti alla sua risposta.
nispio,

2

Utilizzando awk:

awk '/^report|^-t[ho]/' file

Non è un grande risparmio, ma potresti combinare il -th/ -toin -t[ho].
Kevin,

1

L'interrogante ha sollevato due punti:

  • che desidera rimuovere qualsiasi riga che non inizia con "report" o "-th" o "-to".
  • l'output desiderato dovrebbe rimuovere "tutti quei punti e hash indesiderati (sic) intermedi"

Le soluzioni, in questo momento, affrontano il primo punto e quindi anche il secondo. Supponiamo che il file sia più grande e assomigli a:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc
anything else
.. --.
-tp ddd
-tq eee
     -  -----

Affrontare il secondo punto dell'OP non sarebbe utile?

sed -r -i.bak '/^[ |.|-]*$/d' input-file 

svolge il compito di rimuovere presumibilmente linee indesiderate contenenti solo spazi, punti e trattini e conservare il resto, qualunque esso sia.
Penserei che il rischio di entrambi gli approcci sia che la natura del file non sia definita correttamente.


0

Utilizzando Perl:

perl -ne 'print if /^report|^-t[ho]/' filename > newfile

oppure, per effettuare modifiche sul posto (ad esempio sed, perleseguirà anche un backup temporaneo, quindi questo non è vero nella modifica sul posto ):

perl -i.bak -ne 'print if /^report|^-t[ho]/' filename

Ciò farà una copia del file originale chiamato filename.bake sovrascriverà il file originale con la versione modificata.

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.