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


18

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?

Réponses:


26

Avec la commande grep:

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

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

Avec la commande awk:

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

Awk NFvous 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

^.*=sumremplacer tous les caractères ( .*) entre le début de la ligne ( ^) et les derniers caractères ( sum=) par un caractère d'espacement.

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

Cela inclut le sum=et ce n'est pas la même chose que la valeur aprèssum=
Anthon

OP veut la valeur après somme, aussi cette description awk de NF est horrible.

1
Pour compléter cette très bonne réponse, vous pouvez également utiliser cut: cut -d'=' -f2 file.
fedorqui

Ceci est une très bonne réponse. Je l'ai aimé. Je vous remercie.
Jaffer Wilson

6

Si je comprends bien la question, vous souhaitez obtenir uniquement des valeurs après =, et stocker 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

@KasiyA Je ne peux pas reproduire votre problème avec GNU awk 4.0.2. La commande de ma réponse fonctionne également avec -coption (mode de compatibilité avec UNIX traditionnel awkoù les extensions GNU sont désactivées). Veuillez vous assurer que vous avez mis à jour le fichier d'entrée car la question d'origine a été modifiée et les lignes vides supprimées.
jimmij

1

Vous pouvez le faire en 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 devrait contenir certains (plus de 0) symboles non spatiaux;
  2. quelques (plus de 0) symboles non spatiaux après =;

et le format de sa commande en cours d'exécution qui a transféré à travers le tuyau vers bash


Une réponse beaucoup plus polyvalente.
duanev
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.