web-dev-qa-db-fra.com

Extraction d'une partie des lignes avec un motif spécifique en utilisant awk, sed

J'ai une question concernant les opérateurs awk/sed. J'ai un gros fichier qui a répété l'ensemble des lignes suivantes

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

Je veux extraire la valeur après somme dans chaque cas dans un fichier séparé. Est-il possible de le faire d'un seul coup?

19

Avec la commande grep:

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

grep avec le paramètre -P (Perl-regexp) prend en charge \K, qui permet d'ignorer les caractères précédemment mis en correspondance.

Avec la commande awk:

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

Awk NF vous donne le nombre total de champs dans un enregistrement/ligne. Ainsi, la dernière valeur de cela est le dernier numéro de champ dans un enregistrement/ligne.

Avec la commande sed:

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

^.*=sum Remplacez tous les caractères (.*) Entre le début de la ligne (^) Et les derniers caractères (sum=) Par un espace.

Résultat:

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

Si vous souhaitez enregistrer chaque valeur dans un fichier séparé, utilisez les commandes ci-dessus dans une boucle 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
27
αғsнιη

Si je comprends bien la question, vous ne souhaitez obtenir que des valeurs après =, et stockez ces valeurs dans des fichiers séparés, en fonction du deuxième champ (?). Si j'ai raison, essayez quelque chose comme ceci:

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

Le résultat:

$ 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
6
jimmij

Vous pouvez le faire par sed

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

Le script découvre deux morceaux en ligne:

  1. entre les espaces et : et doit contenir certains (plus de 0) symboles non spatiaux;
  2. certains (plus de 0) symboles non spatiaux après =;

et le format de sa commande in execution qui a été transféré via le canal vers bash

1
Costas