Estrarre parte delle linee con un motivo specifico usando awk, sed


18

Ho una domanda relativa agli operatori awk / sed. Ho un file di grandi dimensioni che ha ripetuto le seguenti righe

Expression loweWallrhoPhi :  sum=-6.97168e-09
Expression leftWallrhoPhi :  sum=6.97168e-09
Expression lowerWallPhi :  sum=-5.12623e-12
Expression leftWallPhi :  sum=5.12623e-12
Expression loweWallrhoUSf :  sum=-6.936e-09
Expression leftWallrhoUSf :  sum=6.97169e-09
Expression lowerWallUSf :  sum=-5.1e-12
Expression leftWallUSf :  sum=5.12624e-12

Voglio estrarre valore dopo somma in ogni caso in un file separato. È possibile farlo in una volta sola?

Risposte:


26

Con il comando grep:

grep -oP 'sum=\K.*' inpufile > outputfile

grep con -P(perl-regexp) supporta i parametri \K, che usano per ignorare i caratteri precedentemente abbinati.

Con il comando awk:

awk -F"=" '{print $NF}' inputfile > outputfile

Awk NFti dà il numero totale di campi in un record / riga. Quindi l'ultimo valore è l'ultimo numero di campo in un record / riga.

Con il comando sed:

sed 's/^.*sum=//' inpufile > outputfile

^.*=sumsostituisci tutti i caratteri ( .*) tra l'inizio della riga ( ^) e gli ultimi caratteri ( sum=) con il carattere spazio bianco.

Risultato:

-6.97168e-09
6.97168e-09
-5.12623e-12
5.12623e-12
-6.936e-09
6.97169e-09
-5.1e-12
5.12624e-12

Se vuoi salvare ogni valore in un file separato, usa i comandi sopra in un ciclo while:

while read line; do
    echo "$line" | grep -oP 'sum=\K.*'     > $(echo "$line" |awk '{print $2}');
   #echo "$line" | awk -F"=" '{print $NF}' > $(echo "$line" |awk '{print $2}');
   #echo "#line" | sed 's/^.*sum=//'       > $(echo "$line" |awk '{print $2}');
done < file

Ciò include il sum=e che non è lo stesso del valore successivosum=
Anthon,

OP vuole il valore dopo la somma, anche che la descrizione awk di NF è terribile.

1
Per completare questa risposta molto buona, è anche possibile utilizzare cut: cut -d'=' -f2 file.
fedorqui,

Questa è un'ottima risposta Mi è piaciuto. Grazie.
Jaffer Wilson,

6

Se capisco correttamente la domanda che desideri ottenere solo dopo i valori =e li memorizzo in file separati, in base al secondo campo (?). Se ho ragione, prova qualcosa del genere:

$ awk -F'[ =]' '{print $6>"file_"$2".txt"}' file

Il risultato:

$ ls -1
  file_leftWallPhi.txt
  file_leftWallUSf.txt
  file_leftWallrhoPhi.txt
  file_leftWallrhoUSf.txt
  file_loweWallrhoPhi.txt
  file_loweWallrhoUSf.txt
  file_lowerWallPhi.txt
  file_lowerWallUSf.txt

$ cat  file_leftWallPhi.txt
  5.12623e-12

@KasiyA Non riesco a riprodurre il tuo problema con GNU awk 4.0.2. Il comando dalla mia risposta funziona anche con l' -copzione (modalità di compatibilità con UNIX tradizionale in awkcui le estensioni GNU sono disabilitate). Assicurati di aver aggiornato il file di input quando la domanda originale è stata modificata e le righe vuote eliminate.
Jimmij,

1

Puoi farlo da sed

sed -E 's/^.* (\S+)\s*:.*=(\S+)/echo "\2" > "\1".txt/' file | bash

La sceneggiatura scopre due pezzi in linea:

  1. tra gli spazi e :dovrebbe contenere alcuni (più di 0) simboli non spaziali;
  2. alcuni (più di 0) simboli non spaziali dopo =;

e formatta dal comando in esecuzione che è stato trasferito attraverso la pipe a bash


Una risposta molto più versatile.
duanev,
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.