Extraindo parte de linhas com padrão específico usando awk, sed


18

Eu tenho uma pergunta sobre os operadores awk / sed. Eu tenho um arquivo grande que tem o seguinte conjunto de linhas repetido

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

Eu quero extrair valor após soma em cada caso em arquivo separado. É possível fazê-lo de uma só vez?

Respostas:


26

Com o comando grep:

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

O grep com -Psuporte ao parâmetro (perl-regexp) \K, usado para ignorar os caracteres correspondidos anteriormente.

Com o comando awk:

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

O Awk NFfornece o número total de campos em um registro / linha. Portanto, o último valor desse é o último número do campo em um registro / linha.

Com o comando sed:

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

^.*=sumsubstitua todos os caracteres ( .*) entre o início da linha ( ^) e os últimos caracteres ( sum=) pelo caractere de espaço em branco.

Resultado:

-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 você deseja salvar cada valor em um arquivo separado, use os comandos acima em um loop 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

Isso inclui sum=e não é o mesmo que o valor apóssum=
Anthon

OP quer o valor após a soma, também essa descrição awk de NF é horrível.

11
Para completar esta resposta muito boa, você também pode usar cut: cut -d'=' -f2 file.
Fedorqui

Esta é uma resposta muito boa. Eu gostei. Obrigado.
Jaffer Wilson

6

Se entendi corretamente a pergunta, você deseja obter apenas valores depois =e armazene esses valores em arquivos separados, com base no segundo campo (?). Se eu estiver certo, tente algo assim:

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

O resultado:

$ 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 Não consigo reproduzir o seu problema com o GNU awk 4.0.2. O comando da minha resposta também funciona com a -copção (modo de compatibilidade com o UNIX tradicional, awkonde as extensões GNU estão desabilitadas). Verifique se você atualizou o arquivo de entrada, pois a pergunta original foi editada e as linhas vazias excluídas.
jimmij

1

Você pode fazer isso sed

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

O script descobre duas peças em linha:

  1. entre espaços e :e deve conter alguns (mais de 0) símbolos não espaciais;
  2. alguns (mais de 0) símbolos não-espaciais depois =;

e formato a partir do seu comando em execução que foi transferido através do canal para bash


Uma resposta muito mais versátil.
duanev
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.