web-dev-qa-db-fra.com

utiliser grep pour des lignes particulières dans des fichiers texte

     2              METEOROLOGICAL DATA                         VERSION /      
     8    PR    TD    HR    ZW    ZT    WD    WS    RI      # / TYPES OF   MOD/TYPE/ACC 
  3979316.8350  1050313.7180  4857065.7030      592.1910 PR SENSOR POS XYZ/H           
                                                            END OF HEADER 
 10  1  1  0  0 15  927.9    4.3   99.1                
 10  1  1  0  1 15  927.9    4.3   99.1                
 10  1  1  0  2 15  927.9    4.3   99.1                
 10  1  1  0 15 15  927.9    4.2   99.1               
 10  1  1  0 16 15  927.9    4.2   99.0                
 10  1  1  0 30 15  927.7    4.1   99.1                
 10  1  1  0 31 15  927.7    4.1   99.1                
 10  1  1  0 45 15  927.5    4.1   99.1                
 10  1  1  0 46 15  927.5    4.0   99.1                
 10  1  1  1  0 15  927.4    4.1   99.1                
 10  1  1  1  1 15  927.4    4.1   99.1                

Dans cet exemple de données textuelles, comment puis-je extraire tous les 0,15,30,45 de la cinquième colonne de données numériques dans l’ordre, après la partie "END OF HEADER" comme suit;

10  1  1  0  0 15  927.9    4.3   99.1  
10  1  1  0 15 15  927.9    4.2   99.1 
10  1  1  0 30 15  927.7    4.1   99.1 
10  1  1  0 45 15  927.5    4.1   99.1
10  1  1  1  0 15  927.4    4.1   99.1 
3
deepblue_86

Vous pouvez le faire en utilisant sed et awk:
(en supposant que le texte de votre sujet se trouve dans un fichier nommé example.txt)

sed -n '/END OF HEADER/,${
/END OF HEADER/d
p
}' example.txt | awk '($5 == 0 || $5 == 15 || $5 == 30 || $5 == 45)'

Attribution - la commande awk a été prise à partir du commentaire de steeldriver

Explication

Sed

  • ignorer tout jusqu'à /END OF HEADER/
  • /END OF HEADER/d signifie supprimer la ligne contenant /END OF HEADER/ en dehors de l'espace de modèle, et comme elle n'est plus dans l'espace de modèle, la commande suivante p ne fera rien.
  • p - affiche chaque ligne au fur et à mesure de son insertion dans l'espace du motif

Awk

  • si la colonne 5 correspond à 0 ou 15 ou 30 ou 45, imprimez-la
2
the_velour_fog

Un rapide une ligne serait:

$ awk '$5 == '0' || $5 == '15' ||  $5 == '30' ||  $5 == '45' {print}' test.txt

Comme Fedorqui mentionné dans le commentaire ci-dessous et encore plus rapide, un liner est:

$ awk '$5 ~ /^(0|15|30|45)$/' test.txt

Syntaxe expliquée:

$5  - the desired column from the text.
~   - the match symbol... matching was between the two slashes (/).
^/$ - the regex symbols indicating the beginning and end of the field.
|   - the or specifier for either item in the "()" group.

L'en-tête est filtré en acceptant uniquement les lignes correspondant aux éléments suivant les critères de correspondance ~.

4
L. D. James

Il est parfaitement faisable dans grep, bien que awk soit l'outil à utiliser pour les données séparées par champs.

Avec grep:

grep -E '^10[[:blank:]]+([^[:blank:]]+[[:blank:]]+){3}(0|15|30|45)[[:blank:]]' file.txt
  • Matching 10 au début, ([^[:blank:]]+[[:blank:]]+){3} correspond aux 3 champs suivants, puis au 5ème champ correspondant aux champs souhaités.

Si vous utilisez PCRE (-P), vous pouvez remplacer [:blank:] par \s, cela convient bien aux yeux:

grep -P '^10\s+([^\s]+\s+){3}(0|15|30|45)\s' file.txt     

Exemple:

$ cat file.txt                                        
    2              METEOROLOGICAL DATA                         VERSION /      
    8    PR    TD    HR    ZW    ZT    WD    WS    RI      # / TYPES OF   MOD/TYPE/ACC 
 3979316.8350  1050313.7180  4857065.7030      592.1910 PR SENSOR POS XYZ/H           
                                                           END OF HEADER 
10  1  1  0  0 15  927.9    4.3   99.1                
10  1  1  0  1 15  927.9    4.3   99.1                
10  1  1  0  2 15  927.9    4.3   99.1                
10  1  1  0 15 15  927.9    4.2   99.1               
10  1  1  0 16 15  927.9    4.2   99.0                
10  1  1  0 30 15  927.7    4.1   99.1                
10  1  1  0 31 15  927.7    4.1   99.1                
10  1  1  0 45 15  927.5    4.1   99.1                
10  1  1  0 46 15  927.5    4.0   99.1                
10  1  1  1  0 15  927.4    4.1   99.1                
10  1  1  1  1 15  927.4    4.1   99.1    

$ grep -E '^10[[:blank:]]+([^[:blank:]]+[[:blank:]]+){3}(0|15|30|45)[[:blank:]]' file.txt
10  1  1  0  0 15  927.9    4.3   99.1                
10  1  1  0 15 15  927.9    4.2   99.1               
10  1  1  0 30 15  927.7    4.1   99.1                
10  1  1  0 45 15  927.5    4.1   99.1                
10  1  1  1  0 15  927.4    4.1   99.1                

$ grep -P '^10\s+([^\s]+\s+){3}(0|15|30|45)\s' file.txt                         
10  1  1  0  0 15  927.9    4.3   99.1                
10  1  1  0 15 15  927.9    4.2   99.1               
10  1  1  0 30 15  927.7    4.1   99.1                
10  1  1  0 45 15  927.5    4.1   99.1                
10  1  1  1  0 15  927.4    4.1   99.1        
3
heemayl