Wydobywanie części linii o określonym wzorze za pomocą awk, sed

18

Mam pytanie dotyczące operatorów awk / sed. Mam duży plik, w którym powtarzają się następujące wiersze

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

Chcę wyodrębnić wartość po sumie w każdym przypadku w osobnym pliku. Czy można to zrobić za jednym razem?

Pimpalgaonkar Hrushikesh
źródło

Odpowiedzi:

26

Z poleceniem grep:

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

grep with -P(perl-regexp) obsługuje parametry \K, które służą do ignorowania wcześniej dopasowanych znaków.

Za pomocą polecenia awk:

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

Awk NFpodaje całkowitą liczbę pól w rekordzie / linii. Ostatnią wartością tego jest ostatni numer pola w rekordzie / linii.

Z poleceniem sed:

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

^.*=sumzamień wszystkie znaki ( .*) między początkiem wiersza ( ^) a ostatnimi znakami ( sum=) na białe znaki

Wynik:

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

Jeśli chcesz zapisać każdą wartość w osobnym pliku, użyj powyższych poleceń w pętli 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
αғsнιη
źródło
Obejmuje to sum=i to nie to samo, co wartość posum=
Anthon
OP chce wartości po sumie, a także, że opis NF w awk jest okropny.
1
Aby wykonać tę bardzo dobrą odpowiedź, można również użyć cut: cut -d'=' -f2 file.
fedorqui,
To bardzo dobra odpowiedź. Lubię to. Dziękuję Ci.
Jaffer Wilson
6

Jeśli poprawnie rozumiem pytanie, po którym chcesz uzyskać tylko wartości =, i przechowuję te wartości w osobnych plikach na podstawie drugiego pola (?). Jeśli mam rację, spróbuj czegoś takiego:

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

Wynik:

$ 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
jimmij
źródło
@KasiyA Nie mogę odtworzyć twojego problemu z GNU awk 4.0.2. Polecenie z mojej odpowiedzi działa również z -copcją (tryb zgodności z tradycyjnym systemem UNIX, w awkktórym rozszerzenia GNU są wyłączone). Upewnij się, że zaktualizowałeś plik wejściowy, ponieważ pierwotne pytanie było edytowane, a puste wiersze usunięte.
jimmij
1

Możesz to zrobić przez sed

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

Skrypt znajduje dwa fragmenty w linii:

  1. między spacjami i :powinien zawierać niektóre (więcej niż 0) symbole spacji;
  2. niektóre (więcej niż 0) symbole spacji po =;

i sformatuj z jego polecenia wykonania, które zostało przesłane przez potok do bash

Costas
źródło
O wiele bardziej wszechstronna odpowiedź.
duanev