Les scripts BASH AWK SED

Site de reference : http://unstableme.blogspot.com

Syntaxes equivalentes a : "grep -v"
  1. Une commande equivalente a "grep -v" utilise "split" et est construite automatiquement par le script
  2. Une commande equivalente a "grep -v" utilise "set" : affichage des variables
La commande SED
  1. la syntaxe print 'p' : sed -n '....p' fichier.txt
LES LIGNES SONT DANS UN TABLEAU
  1. Le tableau permet le cumul
  2. Le tableau permet l'ordre inverse
  3. Le tableau permet de selectionner des lignes
  4. Le tableau permet de modifier des fins de lignes
  5. Le tableau permet de modifier des lignes
  6. Le tableau permet d'ajouter des digits
  7. Le tableau permet d'avoir les elements uniques d'une colonne

haut

Une commande equivalente a "grep -v" utilise "split" et est construite automatiquement par le script


# in.txt                                      
the workplace where we carry out our professional activities 
it is a melting pot in which we join our energies
the purpose of the company is to offer an harmonious context
strategically situated in a booming business quarter
that will allow us to efficiently adapt to the evolving needs
up and above its functional aspect , the building embodies the values of excellence
in a multicultural context, the building reflects our unity

# except.txt   # patterns qui vont deleter les lignes
company
building

#!/bin/bash

# le but du script est de deleter les lignes contenant des patterns (equivalent a "grep -v" pour plusieurs patterns)

#################  parametres
count=1
LISTE=except.txt
START=in.txt
RESULT=out.txt    # fichier du resultat
#################  fin des parametres

# deleter les anciens resultats
rm part2.txt

# nb lignes sans les lignes vides
nbline=`grep "." $LISTE | wc -l`
echo $nbline

# boucle sur le nb lignes
until [ "$count" -gt $nbline ]
do
   echo $count > echocount.txt   
   acount=`awk 'NR=='$count' {split( $0, d, " " ) ; print d[1]}' $LISTE`  

   #creation de la syntaxe equivalente a "grep -v"
   echo "awk 'FNR==NR &&" > part1.txt
   echo "a[\$0]=/$acount/ ||" >> part2.txt ; sed -e '$ s/||//g' part2.txt > part2b.txt    
   echo "{b[\$0] ; next} !(\$0 in b)' \$START" > part3.txt
   cat part1.txt part2b.txt part3.txt > action.txt
   ACTION=`cat action.txt`
   eval `echo $ACTION` > $RESULT
let count=count+1
done

# resultat
the workplace where we carry out our professional activities 
it a melting pot in which we join our energies
strategically situated in a booming business quarter
that will allow us to efficiently adapt to the evolving needs

haut

Une commande equivalente a "grep -v" utilise "set" : affichage des variables


# in.txt                                      
the workplace where we carry out our professional activities 
it is a melting pot in which we join our energies
the purpose of the company is to offer an harmonious context
strategically situated in a booming business quarter
that will allow us to efficiently adapt to the evolving needs
up and above its functional aspect , the building embodies the values of excellence
in a multicultural context, the building reflects our unity

# except.txt   # patterns qui vont deleter les lignes
company
building

#!/bin/bash

# le but du script est de deleter les lignes contenant des patterns (equivalent a "grep -v" pour plusieurs patterns)

#################  parametres
count=1
LISTE=except.txt
START=in.txt
RESULT=out.txt    # fichier du resultat
#################  fin des parametres

# deleter auciens resultats
rm part2.txt

# nb lignes sans les lignes vides
nbline=`grep "." $LISTE | wc -l`
echo $nbline

# initialiser les variables
variables=`cat except.txt`
set -- $variables

# nombre de mots dans le fichier: variable speciale $#
for i in `seq 1 $#`
do
t=`echo var$i="\$"{$i} "; echo \$"var$i`
echo $t
done > tmp.txt

# creation des variables
while read line ; do eval $line ; done < tmp.txt 

until [ "$count" -gt $nbline ]
do
   echo "awk 'FNR==NR &&" > part1.txt
   echo "a[\$0]=/'\$var$count'/ ||" >> part2.txt ; sed -e '$ s/||//g' part2.txt > part2b.txt    
   echo "{b[\$0] ; next} !(\$0 in b)' \$START" > part3.txt
   cat part1.txt part2b.txt part3.txt > action.txt
   ACTION=`cat action.txt`
   eval `echo $ACTION` > $OUT
let count=count+1
done

# resultat
the workplace where we carry out our professional activities 
it is a melting pot in which we join our energies
strategically situated in a booming business quarter
that will allow us to efficiently adapt to the evolving needs

haut

la syntaxe print 'p' : sed -n '....p' fichier.txt


# in.txt
line1 data
line2 data2 test sed command
line3 513
line4 data4
line5

# print la ligne 2  :

sed -n '2p' in.txt

# resultat : 
line2 data2 test sed command
#-----------------------

# print de la ligne 2 a 4  : 
 
sed -n '2,4p' in.txt

# resultat : 
line2 data2 test sed command
line3 513
line4 data4
#-----------------------

# print la 1ere et derniere ligne :  

sed -n '1p ; $p' in.txt

# resultat :
line1 data
line5
#-----------------------
 
# print si la ligne a au moins 6 caracteres :  

sed -n '/^.\{6\}/p' in.txt

# resultat :
line1 data
line2 data2 test sed command
line4 data4
#-----------------------

# print un pattern :  

sed -n '/data/p' in.txt

# resultat :
line1 data
line2 data2 test sed command
line4 data4
#-----------------------

# print entre 2 patterns :  

sed -n '/data2/,/data4/p' in.txt

# resultat :
line2 data2 test sed command
line3 513
line4 data4
#-----------------------

# print un pattern mis en variable :
 
var=sed
sed -n '/'$var'/p' in.txt

# resultat :
line2 data2 test sed command
#-----------------------

# ne pas printer un pattern :  

sed -n '/data/!p' in.txt

# resultat :
line3 513
line5
#-----------------------

# print 3 digits consecutifs :  

sed -n '/[0-9]\{3\}/p' in.txt

# resultat
line3 513
#-----------------------

# print le nombre minimum de champs des lignes d'un fichier : 
 
awk '{print NF}' in.txt | sort -n | sed -n '1p'
 
# resultat
1
#-----------------------

# print le nombre maximum de champs des lignes d'un fichier :  

awk '{print NF}' in.txt | sort -n | sed -n '$p'

# resultat
5

haut

Le tableau permet le cumul


# in.txt                                      
line1 1
line2 2
line3 3
line4 4

awk '{arr[NR] = $2 ; sum+= $2}      # oubien :  {arr[NR] = $0 " " sum+= $2}
END {
for (i = 1 ; i<= NR ; i++)
printf "%s(%2.2f %)\n" , arr[i],(100 * arr[i])/sum
}' FS=" " in.txt

# resultat
1(10.00 %)
2(10.00 %)
3(10.00 %)
4(10.00 %)

haut

Le tableau permet l'ordre inverse


Noter que ce qui suit peut etre obtenu plus rapidement avec : tac in.txt

# in.txt                                      
line1 1
line2 2
line3 3
line4 4

awk '{ arr[NR]=$0 }
END {
for (i=NR; i>=1; i--)
print arr[i]
}' in.txt

# resultat
line4 4
line3 3
line2 2
line1 1

haut

Le tableau permet de selectionner des lignes


# voici une liste de magasins (de marque 1, 2 ou 3) avec leur nombre de parkings dans quelques villes
# le but est de selectionner la ville qui n'a que le magasin1 et plus de 5 parkings

# in.txt   (colonne 1 : ville /// colonne 2 : magasin /// colonne 3 : nombre de parkings)
marseille   marque1   7
marseille   marque2   10
marseille   marque3   3

lyon        marque1   2
lyon        marque3   9

rennes      marque1   3

bordeaux    marque2   4

strasbourg  marque1   8

#!/bin/bash
######    parametres

parking="5"

######    fin des parametres

# cas ou on s'interesse uniquement au magasin  marque[$1]

awk '
# creer le tableau  marque1[$1]  
# (on ne peut ecrire ici la synthaxe  « delete marque1[$1] »
# puisque le tableau  marque1[$1]  n’est pas encore cree)
$3 > '$parking' && $2 == "marque1" && !($1 in marque2) && !($1 in marque3) {marque1[$1]}

# si la ville possede marque2 , retirer la ville de marque1
$3 > '$parking' && $2 == "marque2" {marque2[$1] ; delete marque1[$1]}

# si la ville possede marque3 , retirer la ville de marque1
$3 > '$parking' && $2 == "marque3" {marque3[$1] ; delete marque1[$1]}

END {
for (ville in marque1) print "la ville qui n a que la marque1 et plus de 5 parkings est : " ville
}
' in.txt

# resultat
la ville qui n a que la marque1 et plus de 5 parkings est : strasbourg

haut

Le tableau permet de modifier des fins de lignes


# in.txt                                      
H0104 STREAMER DETAILS          MAL PORT STREAMER            1       0
H0105 OTHER DETAILS             OEX Outer STBD TAILBUOY      1           0
R 283 487217.26818026.9     284 487229.76818026.3     285 487242.26818025.6    9
R 286 487254.66818025.0     287 487267.16818024.3     288 487279.66818023.7    9
R   1 483732.86818401.6       2 483745.26818400.0       3 483757.66818398.4    0
R   4 483770.06818396.8       5 483782.46818395.3       6 483794.86818393.9    0

awk '{ f[NR]=$0 }
END {
for (i=1; i<=NR; i++)
if (length(f[i]) == 80)
{print f[i]"@"}
else
{print f[i]}
}' in.txt | sed 's/9@/9/g' | sed 's/0@/A/g'

# resultat (attention de ne pas transformer toutes les lignes se terminant par 0)
H0104 STREAMER DETAILS          MAL PORT STREAMER            1       0
H0105 OTHER DETAILS             OEX Outer STBD TAILBUOY      1           0
R 283 487217.26818026.9     284 487229.76818026.3     285 487242.26818025.6    9
R 286 487254.66818025.0     287 487267.16818024.3     288 487279.66818023.7    9
R   1 483732.86818401.6       2 483745.26818400.0       3 483757.66818398.4    A
R   4 483770.06818396.8       5 483782.46818395.3       6 483794.86818393.9    A

haut

Le tableau permet de modifier des lignes


# in.txt                                      
line1 1 data1
line2 2 data1
line3 3 data2
line4 4 data2

awk '{ f[NR]=$3 ; g[NR]=$1" "$2 }
END {
for (i=1; i<=NR; i++)
if (f[i] != f[i-1])
{print "@",f[i],g[i]}
else
{print f[i],g[i]}
}' in.txt | sed '/@/G'

# resultat
@ data1 line1 1

data1 line2 2
@ data2 line3 3

data2 line4 4

haut

Le tableau permet d'ajouter des digits


Noter que ce qui suit peut etre obtenu plus rapidement avec : seq -w 11

seq 11 | awk '{
arr[NR] = $0
arr[NR] = (length(NR)==1 ? "0"NR : NR) }
END {
for (i=1; i<=NR; i++)
{print i,arr[i]}
}' | sort -n

# resultat
.....
8 08
9 09
10 10
11 11

haut

Le tableau permet d'avoir les elements uniques d'une colonne


# in.txt                                      
100
100
100
101
101
102
102

awk '{ arr[$1]++ }
END {
for (i in arr) print i}
' in.txt

# resultat
100
101
102

haut

Derniere modification : Fevrier 2013