Sed awk

De Wiki de Nelly & Richard
Sauter à la navigation Sauter à la recherche

Expressions régulières

  • Les expressions régulières sont utiles au quotidien dans l'utilisation de scripts, de programmation, egrep, ...
  • Voici quelques outils qui vous aideront pour la réalisation de scripts.

Le caractère d'échappement \

  • Le back-slash permet de désigner les caractères spécifiques suivant : . * ^ $ \ [ ]
exemple :
$ echo 'c:\' | grep '\\'
> nous renvoi bien c:\

Le point . et l'astérisque *

  • Le point est aussi appelé caractère joker, il permet de remplacer n'importe quel caractère.
exemple :
$ echo "test" | grep 't.st'
> nous renvoi bien test
  • L'astérisque lui va nous permettre de désigner 0, 1 ou plusieurs occurrences du caractère précédent
exemple :
$ echo "ttttttt" | grep 't*'
> nous renvoi bien ttttttt

de même :
$ echo "test" | grep 'tei*st'
> nous renvoi bien test

L'accent circonflexe ^ et dollar $

  • Ces deux caractères indique respectivement le début et la fin d'une ligne
exemple :
$ echo "test" | grep '^test$'
> nous renvoi bien test

à l'inverse
$ echo "test" | grep '^tes$'
> ne renvoi rien
  • Il peuvent rechercher une ligne vide : '^$'

Les crochets [ ] pour l'alternative

  • Les crochets permettent de définir le ou logique
exemple :
$ echo "test" | grep 't[ei]st'
> renvoi test

de même :
$ echo "tist" | grep 't[ei]st'
> renvoi tist

ou : 
$ echo "teist" | grep 't[ei]*st'
> renvoi teist
  • Le tiret - permet de définir une plage (les chiffres de 2 à 7 -> [2-7])
exemple :
$ echo "tEst" | grep 't[a-fA-F]st'
> renvoi tEst

Les crochets [^ ] pour la négation

  • Les crochets utilisés avec l'accent circonflexe permettent d'exprimer la négation
exemple :
$ echo "test" | grep 't[^e]st'
> ne renvoi rien
de même :
$ echo "tist" | grep 't[^e]st'
> renvoi tist

Les parenthèses \( \) pour les groupes

  • Les parenthèses permettent d'isoler un groupe de caractères pour le rappeler éventuellement, l'exemple qui suit utilise sed nous verrons plus en détail les possibilité de cette commande plus bas.
exemple :
$ echo "Quel beau paysage" | sed -e 's/^\(Quel beau\).*$/\1 tableau/'
> renvoi : Quel beau tableau

Les éléments compris entre \( \) sont rappelés avec \1, \2 si il y a 2 sous ensemble, ...

Les accolades \{ \}

  • Les accolades définissent le nombre d'occurrences du caractère, sous ensemble ou alternative qui les précèdent.
exemple :
$ echo "teeest" | grep 'te\{3\}st'
> renvoi : teeest
  • Comme les parenthèses les accolades sont utilisées avec les back-slash \{ \}

sed

  • Sed permet d'effectuer des manipulations simples sur des fichiers textes. Vous trouverez des informations dans la manpage de sed ou l'infopage de sed répondront à toutes vos questions.
  • dans les exemples qui suivent j'utiliserais ce fichier sed.txt :
azerty
AZERTY
01234
azErty0uiOp3qsdf6
a z e r t y
a/z/e/r/t/y

blabla

bla bla bla 


options

  • -i : enregistre les modifications dans le fichier traité.
sed -i 'expression' fichier
  • -e : permet d'appeler plusieurs commandes à la suite.
sed -e 'expression' -e 'expression' fichier
  • -n : silencieux utilise avec p.
# même comportement qu'un cat
sed -n 'p' fichier
  • -f : utilisation d'un fichier script.

le format du fichier script est :

'expression'
'expression'
...
# usage : sed -f file-script fichier

expressions

syntaxe

  • De manière générale :
'<début_recherche>,<fin_recherche><commande>'
  • <début_recherche> et <fin_recherche> peuvent-être des numéros de ligne ou bien des expressions régulière.
  • plusieurs <commande> peuvent être placées.
sed -n '2,/[0-9]/p' sed.txt
# recherchera à partir de la 2° ligne jusqu'au prochain caractère numérique
# renvoie :
AZERTY
01234

subtitution

Elle doit-être de loin la plus connue vous l'utilisez peut-être déjà avec vim

  • syntaxe : 's/<expression régulière>/<chaîne de remplacement>/'
  • exemple :
sed -n '2,/[0-9]/s/[0-9]/Number/p' sed.txt
# renvoie :
Number1234
  • vous pouvez spécifier une sous-chaîne et la rappeler dans la chaîne de remplacement \n
  • exemple :
sed -n '2s/\(AZ\)E/\1@/p' sed.txt
# renvoie :
AZ@RTY

suppression

divers

  • g : répète la commande tant que le texte recherché est trouver.
  • exemple :
sed -n 's/a/@/pg' sed.txt 
# renvoie :
@zerty
@zErty0uiOp3qsdf6
@ z e r t y
@/z/e/r/t/y
bl@bl@
bl@ bl@ bl@
  • i : ignore la casse
  • exemple :
sed -n 's/a/@/pgi' sed.txt 
@zerty
@ZERTY
@zErty0uiOp3qsdf6
@ z e r t y
@/z/e/r/t/y
bl@bl@
bl@ bl@ bl@

awk

  • Awk est un langage qui permet également la manipulation de chaînes de caractères et/ou de fichiers texte. En l'utilisant de façon avancée vous obtiendrez la puissance d'un tableur.
  • Ce qui suit est vraiment un survol des possibilités de g(awk), la manpage de awk ainsi que les liens en bas de page vous permettrons d'en savoir d'avantage.
  • pour les exemples qui vont suivre nous utiliserons le fichier généré aléatoirement : awk_wiki.csv

options courantes

  • -F : désigne le séparateur de champs, par défaut il s'agit de l'espace
$ echo 'toto,titi' | awk -F ',' '{print $2}'
titi
pour rappel :
 \\        \
 \"        "
 \a        alert, ascii 7
 \b        backspace, ascii 8
 \t        tab, ascii 9
 \n        newline, ascii 10
 \v        vertical tab, ascii 11
 \f        formfeed, ascii 12
 \r        carriage return, ascii 13
  • -f : permet de faire appel à un fichier texte contenant le script
# test.awk :
{
 print $2
}
$ echo 'toto,titi' | awk -F ',' -f test.awk
titi
  • -v : indique une variable venant de l'extérieure
$ echo 'toto,titi' | awk -F ',' -v maVar="teste les variables" '{print $2 " " maVar}'
titi teste les variables

utilisations

syntaxe générale

  • De manière générale awk exécute pour chaque ligne les instructions contenu dans chaque bloc si les lignes et/ou éléments correspondent aux conditions, expressions, ... définis :
conditions et/ou regexp
{
 instructions1
 instructions2
 ...
}
...
  • les blocs BEGIN et END

Ces deux blocs sont particuliers, ils permettent le traitement d'instructions avant et après l'exécution des blocs standards.

# exemples avec le fichier awk_wiki.csv
BEGIN {
 ligne=0
}

# match le champ 4 commençant par un G
$4 ~ /^G/ {
 ligne+=1
}

END {
 print "match : " ligne " ligne(s)"
}
# résultat :
# match : 45 ligne(s)

exemples

Étant donné que le man 1 mawk contient tout ce dont vous avez besoin pour utiliser awk je vous laisse la consulter en parcourant ces exemples, j'essaierais tout de même de les commenter.

  • Modification de notre fichier awk_wiki.csv
# ajout de la taille du champs 3 et 4 en début de ligne
$ awk -F ',' '{result=length($3) "," length($4) "," $0; print result ; ligne++}' awk_wiki.csv > test2.csv
  • Bon on se fait un peu chier là :(

nombre d'occurences

# exemple fichier test2.awk

# initialisation des variables
BEGIN {
FS=","
ligne=0
}

# match des champ1 présent plus d'une fois dans le fichier
!list[$1]++ {
 ligne++
}

# pour toutes les lignes on compte le nombre d'occurrences des éléments de list
# on stock le tout dans list2
{
 for (i in list) {
   if (i == $1)
     list2[i]+=1
 }
}

# affichage des résultats 
END {
 for (i in list)
   print "$1 contient " list2[i] " fois la valeur " i
   print "------------------\n" ligne " valeurs uniques"
}

# resultat : awk -f test2.awk test2.csv
# $1 contient 129 fois la valeur 10
# $1 contient 113 fois la valeur 11
# $1 contient 1 fois la valeur 3
# $1 contient 120 fois la valeur 4
# $1 contient 120 fois la valeur 5
# $1 contient 142 fois la valeur 6
# $1 contient 129 fois la valeur 7
# $1 contient 109 fois la valeur 8
# $1 contient 138 fois la valeur 9
# ------------------
# 9 valeurs uniques
  • nombre d'occurences

On utilisera un fichier sous ce format :

data1 data2 data3 c1 c2 c3 c4 c5 e1 e2
1 < c < 50 et 1 < e < 9
{
 # on rempli les listes
 c1[NR]=$4
 c2[NR]=$5
 c3[NR]=$6
 c4[NR]=$7
 c5[NR]=$8

 e1[NR]=$9
 e2[NR]=$10
} 

END {
 # on compte le nombre de 1, de 2, ... par liste
 i=0
 while (i < 50) {
   i++
   for (c in c1) {
     if (c1[c] == i) {
       liste1[i] = liste1[i]+1
     }
     if (c2[c] == i) {
       liste2[i] = liste2[i]+1
     }
     if (c3[c] == i) {
       liste3[i] = liste3[i]+1
     }
     if (c4[c] == i) {
       liste4[i] = liste4[i]+1
     }
     if (c5[c] == i) {
       liste5[i] = liste5[i]+1
     }
     if (e1[c] == i) {
       liste6[i] = liste6[i]+1
     }
     if (e2[c] == i) {
       liste7[i] = liste7[i]+1
     }
   }
 }
 # impression du résultat
 i = 0
 while (i < 50) {
   i++
   print i "\t: " liste1[i] "\t"  liste2[i] "\t" liste3[i] "\t" liste4[i] "\t" liste5[i] "\t" liste6[i] "\t" liste7[i]
 }
}

Match et fonctions

# initialisation variables
BEGIN {
  FS=","
  ligne=0
}

# recherche de la ligne 901 à 910
FNR > 900 && FNR <= 910 {
  print FNR " " $0 "\n$4 : " $4
  # recherche et remplace toutes les occurrences de "bg" dans le champ 4 
  gsub("bg", "#", $4)
  # utilisation du \ (\t : tab, \n : retour chariot, ...)
  print "gsub(\"bg\", \"#\", $4) : " $4 ; ligne++
}

# retourne le nombre de lignes matchées
END {
  print "lignes matchées : " ligne
}

Un autre ?

# fichier awk_wiki.csv
# recherche de la ligne 901 à 909
FNR > 900 && FNR < 910 {
  print $3
  ligne++
}

# champ 3 commence par G et champ 2 ne se terminant pas par A à L
$3 ~ /^G/ && $2 !~ /[A-L]$/ {
  print $2 " " $3
  ligne++
}

# retourne le nombre de lignes matchées
END {
  print "lignes matchées : " ligne
}

Un dernier juste pour la syntaxe

# manipulation d'une liste
# itération
# commande system
# variables awk : FILENAME, ARGV
# awk -f fichier.awk fichier1.csv fichier2.csv

BEGIN {
  FS = ","
  # just for fun :)
  for (i in ARGV) {
    print ARGV[i]
    print i }
}

(FILENAME == "fichier1.csv") {
  system("test -d /chemin/" $2 "> /tmp/test1")
  getline test1 < "/tmp/test1"
  system("rm /tmp/test1")
  if (test1 == 0) {
    lstLogin[$1] = "/chemin/" $2 }
  system("test -d /chemin/" $1 "> /tmp/test2")
  getline test2 < "/tmp/test2"
  system("rm /tmp/test2")
  if (test2 == 0) {
    lstLogin[$1] = "/chemin/" $1 }
}

(FILENAME == "fichier2.csv") {
  for (i in lstLogin) {
    if ($1 == i) {
      print lstLogin[i] " /chemin2/" $3 "/" $1 } }
}

Liens externes