Les scripts BASH AWK SED

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

LA COLONNE

MIN - MAX
  1. Min et Max d'une colonne
  2. Min et Max d'une colonne avec choix des limites de coupe
CUMUL
  1. Cumul d'une colonne en regroupant des patterns semblables (associative array)
  2. Cumul d'une colonne avec limite de coupe manuelle
  3. Cumul d'une colonne avec limite de coupe automatique
DIVERS
  1. Afficher les elements uniques d'une colonne
  2. Lire les colonnes avec "while read col1 col2 ..."
  3. Repeter un nombre de fois different une valeur qui s'incremente de 1
  4. Modifier une colonne avec l'action : "if(length())"
  5. Decoupe verticale avant ou apres un separateur ( identique a split )
  6. Reperer les doublons d'une colonne en separant les series dont ils sont issus
  7. Decouper un fichier en creant autant de fichiers que de colonnes

LA LIGNE

MIN - MAX - CUMUL
  1. Min et Max de valeurs placées sur une ligne
  2. Cumul de valeurs sur une ligne
MODIFIER LE DEBUT , LA FIN OU TOUT CARACTERE D' UNE LIGNE
  1. Supprimer un debut de fichier avant un pattern
  2. Supprimer une fin de fichier apres un pattern
  3. Modifier les extremites d'une ligne avec "gsub" (bash)
  4. Modifier une fin de ligne en retirant un caractere (bash)
  5. Modifier une fin de ligne en ajoutant un caractere (bash)
  6. Modifier une fin de ligne en changeant un caractere (awk)
  7. Modifier tout caractere en maitrisant sa position (awk)
  8. Un signe en bout de ligne fait joindre la ligne qui suit (awk + getline)
  9. Lire les 3 premiers caracteres de chaque ligne d'un fichier
  10. Lire les 3 derniers caracteres de chaque ligne d'un fichier
  11. Effacer les 3 derniers caracteres de chaque ligne d'un fichier
TESTER LES FINS DE LIGNES
  1. En "AWK" : tester les tabulations cachees en fin de lignes
  2. En "BASH" : tester les derniers caracteres en fin de lignes
DECOUPER UN FICHIER
  1. Decouper un fichier a un pattern precis (le pattern est la fin du fichier decoupe)
  2. Decouper un fichier a un pattern precis (le pattern est le debut du fichier decoupe)
  3. Decouper un fichier a un pattern precis (autre exemple)
  4. Decouper un fichier d'apres la forme de sa fin de ligne
AJOUTER - INSERER
  1. Inserer un trait au changement d'un pattern
  2. Inserer une ligne avant des patterns listes dans un fichier
  3. Ajouter du texte sur une ligne ou apres une ligne
  4. Inserer une ligne suivant un pattern
  5. Inserer une ligne blanche selon un critere de longueur de ligne
  6. Memoriser une chaine de caracteres pour l'inserer sur une autre ligne
CAPTURER - MODIFIER
  1. Capturer dans un fichier des patterns listes dans un 2eme fichier (exemple 1)
  2. Capturer dans un fichier des patterns listes dans un 2eme fichier (exemple 2)
  3. Modifier dans un fichier des patterns listes dans un 2eme fichier
  4. Stopper la lecture d'un fichier à un pattern liste dans un 2eme fichier
  5. Capturer un pattern a une position fixe sur une ligne
  6. Capturer un pattern avec un depart, une longueur et une arrivee
  7. Capturer la premiere occurrence d'une serie de lignes ayant meme pattern
  8. Selectionner des lignes d'un fichier par des caracteres d'une colonne
  9. Capture de lignes avec pattern de debut et de fin
  10. Maitrise de la ligne et du champ pour reorganiser les champs
COLLER - MARQUER
  1. Marquer des groupes de patterns semblables (exemple simple)
  2. Marquer des groupes de patterns semblables (exemple plus complique)
  3. Coller des valeurs a un pattern (exemple 1)
  4. Coller des valeurs a un pattern (exemple 2)
  5. Coller des valeurs a un pattern (exemple 3)
  6. Un titre de paragraphe devient marqueur (en utilisant 'split')
  7. Un titre de paragraphe devient marqueur (sans utiliser 'split')
  8. Un champ d'une ligne devient titre de la ligne (sans utiliser 'split')
L'OCCURRENCE D'UN PATTERN
  1. Occurrences d'un pattern
  2. Marquer les numeros des occurrences a partir d'une liste de patterns
  3. Deleter les occurrences repetees dans une colonne, et ne garder que la 1ere
  4. Occurrences d'un caractere dans plusieurs fichiers
INCREMENTER DES LIGNES CONSECUTIVES DE SYNTAXE IDENTIQUE
  1. Incrementer des lignes consecutives de format identique, le compteur est mis a zero ensuite
JOINDRE
  1. Joindre un signe avec la ligne suivante (exemple 1)
  2. Joindre un signe avec la ligne suivante (exemple 2)
  3. Joindre un signe avec la ligne suivante (exemple 3)(awk + getline)
  4. Joindre un signe au bout de la ligne precedente (exemple 1)
  5. Joindre un signe au bout de la ligne precedente (exemple 2)
  6. Joindre un signe au bout de la ligne precedente sauf si cette derniere se termine par @ (exemple 3)
  7. Les lignes qui commencent par un signe collent les suivantes a leur fin si elles ne possedent pas ce signe
COMPARER 2 FICHIERS
  1. Printer les lignes du fichier2 qui manquent dans le fichier1
  2. Comparer 2 fichiers : identiques ou differents
  3. Intersection de 2 fichiers : lignes uniques et communes
DIVERS
  1. Un titre de paragraphe est capture a un pattern
  2. Operations entre lignes 'n+1' et 'n'
  3. Supprimer des caracteres entre 2 bornes connues
  4. Supprimer des lignes doubles

haut

Min et Max d'une colonne


# in.txt
694
1004
438

# methode courte ( min et max )
awk 'min=="" || $1 < min {min=$1}
END {print min}' FS=" " in.txt      # 438

awk 'max=="" || $1 > max {max=$1}
END {print max}' FS=" " in.txt      # 1004

# methode longue ( max )
array=(`cat in.txt`)
max=0
len=${#array[*]}
i=0
while [ $i -lt $len ]
do
val=`echo "${array[$i]}"`
if [ $(echo "$max < $val" | bc) -eq 1 ]
then
max=$val
fi
let i++
done 
echo "max is => $max"     # max is => 1004

haut

Min et Max d'une colonne avec choix des limites de debut de coupe


# in.txt 
70 1001
50 1002
30 1003
20 1005
30 1006
40 1007

# compteur.txt
1001 1003
1005 1007

#!/bin/bash
while read var1 var2
do
if [ -e temp.txt ] ; then rm temp.txt ; fi
   until [ $var1 -gt $var2 ]
   do
   var3=`awk '$2 ~ '$var1' {print $1}' in.txt`
   echo $var3 >> temp.txt
   echo $var3
   
min=`awk 'min=="" || $1 < min {min=$1} END {print min}' temp.txt`
max=`awk 'max=="" || $1 > max {max=$1} END {print max}' temp.txt`

   let var1=var1+1
   done
echo "min= " $min "  ;  max= " $max
done < compteur.txt > temp2.txt

awk '/min/ {print $0}' temp2.txt > temp3.txt
paste compteur.txt temp3.txt

# resultat
1001 1003    min= 30  ;  max= 70
1005 1007    min= 20  ;  max= 40

haut

Cumul d'une colonne en regroupant des patterns semblables (associative array)


# in.txt
100 1001
100 1002
100 1003
101 1004
101 1005

#!/bin/bash
awk '{ arr[$1]+=$2 }
END{ for( i in arr )
{print i, arr[i]}
}' in.txt | sort -n

# resultat
100 3006
101 2009

haut

Cumul d'une colonne avec limite de coupe manuelle


#!/bin/bash

# but du script : cumuler a l'aide d'un compteur.
# La 1ere ligne du compteur (1001 1003) indique
# qu'il y aura cumul de la colonne 1 de 1001 a 1003.

############ parametres:
# fichier depart : in.txt 
#     70 1001
#     50 1002
#     30 1003
#     20 1004
#     30 1005
#     40 1006

# compteur.txt
#     1001 1003
#     1004 1006    # supprimer le dernier retour chariot

IN=in.txt                 # changer ici les noms des fichiers
COMPTEUR=compteur.txt
OUT=out.txt

########### fin des parametres

while read var1 var2
do
sum=0      # desactiver cette ligne pour le cumul de toutes les lignes
   until [ $var1 -gt $var2 ]
   do
   var3=`awk '$2 ~ '$var1' {print $1}' $IN`
   echo $var3
   ((sum+=$var3))
   let var1=var1+1
   done
echo "s= " $sum
done < $COMPTEUR > tmp1.txt

awk '/s=/ {print $2}' tmp1.txt > tmp2.txt
paste $COMPTEUR tmp2.txt > tmp3.txt
awk '{print $1"-"$2," cumul = "$3}' tmp3.txt > $OUT
cat $OUT

# resultat
#     1001-1003  cumul = 150
#     1004-1006  cumul = 90

haut

Cumul d'une colonne avec limite de coupe automatique


#!/bin/bash

#######  parametres  #############
LIMIT=7
IN=stmdepart.txt
OUT=stmresult.txt
###
# stmdepart.txt
#    3
#    2
#    5    # une seule colonne de valeurs (sans compteur)
#    1
#    6
#    4
#    2    # sans retour chariot final

#######  fin des parametres  ############

### script
awk '{print total+=$1}' $IN > inter2.txt
paste $IN inter2.txt > inter3.txt

# si le cumul > $LIMIT
cat inter3.txt | awk '{
# ajouter syntaxe si necessaire :  < '$LIMIT' ? total3 : (total4+=$1) < '$LIMIT' ? total4 : (total5+=$1)    
f[$2] = ($2 < '$LIMIT' ? $2 : (total+=$1) < '$LIMIT' ? total : (total2+=$1) < '$LIMIT' ? total2 : (total3+=$1))
{print f[$2]}
}' > inter4.txt

# mettre les lignes en tableau
awk '{f[NR] = $0}
END {
for (i=1; i<=NR; i++)
if (f[i+1] <= f[i])
{print f[i],"@"}     # ajouter un marqueur
else
{print f[i]}
}' inter4.txt > inter5.txt

# creer un compteur a la repetition d'un pattern
while read line
do echo "$line"
if [[ "$line" =~ "@" ]] ; then echo "------ tape " ; fi
done < inter5.txt | sed -e '1i \------ tape ' | sed '$d' | sed 's/@//g' > inter6.txt 

# habillage final
# marquer les occurrences du pattern "@"  (et effacer les marqueurs inutiles)
awk '/tape/ {i=i+1} {print $0,i}' inter6.txt |
awk '!a[$NF]++ {print $0 ; next} { sub($NF, "") ; print }' > $OUT ; cat $OUT

# resultat
#     --- tape 1
#     3
#     5
#     --- tape 2
#     5
#     6
#     --- tape 3
#     6
#     --- tape 4
#     4
#     6

haut

Afficher 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

Lire les colonnes avec "while read col1 col2 ..."


# in.txt
line1 col2 data1
line2 col2 data2
line3 col2 data3

#!/bin/bash
while read col1 col2    # col2 se voit attribuer tout le reste des colonnes
do
echo $col2
done < in.txt

# resultat
col2 data1
col2 data2
col2 data3

haut

Repeter un nombre de fois different une valeur qui s'incremente de 1


#!/bin/bash

################  parametres

# valeurs de debut et de fin du compteur incremente de 1 :
first=810828     # 1ere valeur 
last=810830      # derniere valeur

OCCUR=in-occur.txt   # le dernier retour chariot sera delete automatiquement
OUT=out.txt

# contenu de OCCUR ( occurrence de chaque valeur )
# 3     # 1ere valeur repetee 3 fois
# 2     # 2eme valeur repetee 2 fois
# 4     # 3eme valeur repetee 4 fois

################  fin des parametres

# deleter le dernier retoue chariot
cat $OCCUR | grep "." > temp-occur.txt

# creation du compteur qui s'incremente de 1
seq $first $last > temp1.txt

# temp1.txt
# 810828
# 810829
# 810830

# fichier de base 
paste temp1.txt temp-occur.txt > temp2.txt

# temp2.txt
# 810828	3
# 810829	2
# 810830	4

# creation du compteur des occurrences
while read line
do
seq 1 $line
done < temp-occur.txt > temp3.txt

# temp3.txt
# 1
# 2
# 3
# 1
# 2
# 1
# 2
# 3
# 4

###############
          
# boucle
while read col1 col2
do

   COUNTER=1
   until [  $COUNTER -gt $col2 ]
   do          
   echo $col1 
   let COUNTER=COUNTER+1               
   done                                    

done < temp2.txt > temp4.txt

# temp4.txt
# 810828
# 810828
# 810828
# 810829
# 810829
# 810830
# 810830
# 810830
# 810830

# habillage final
paste temp4.txt temp3.txt > $OUT 
# fin du script

# resultat
# 810828	1
# 810828	2
# 810828	3
# 810829	1
# 810829	2
# 810830	1
# 810830	2
# 810830	3
# 810830	4

haut

Modifier une colonne avec l'action : "if(length())"


# in.txt
line1 1field data1
line2 data2

line3 3field data3

#!/bin/bash
awk 'BEGIN{FS=" "; OFS=" "}
{ if ( length($0) )
{ $0 = substr($0, 0, 5) }
else { $0 = "NA" }
print
}' in.txt

# resultat
line1
line2
NA
line3

haut

Decoupe verticale avant ou apres un separateur ( identique a split )


# in.txt
col1data1,a,col3new1
col1data2,b,col3new2
col1data3,c,col3new3

#!/bin/bash
while read line
do
# le separateur est ici: ','
echo ${line%%,*}     # (la fin du fichier est supprimee)
done < in.txt

# resultat:
col1data1
col1data2
col1data3

#!/bin/bash
while read line
do
# le separateur est ici: ','
echo ${line##*,}     # (le debut du fichier est supprime)
done < in.txt

# resultat:
col3new1
col3new2
col3new3

haut

Reperer les doublons d'une colonne en separant les series dont ils sont issus


#in.txt
10 4000
10 3400
10 4000
10 2800
11 300
11 300
11 200
11 100
11 100
11 100
###############  parametres   ####################

IN=in.txt     # fichier de depart  (changer ici le nom du fichier)

###############  fin des parametres  ##################

#creation d'un compteur
awk '{print $1}' $IN > in-count.txt

#elements uniques de la colonne 1
awk '{a[$1]++} END {for(k in a) print k}' in-count.txt > in-count2.txt

#ajout d'un marqueur devant la colonne 1
awk '{print "@"$1,$2}' $IN > in2.txt

if [ -e in3.txt ] ; then rm in3.txt ; fi
while read line
do
awk '
$1 ~ /'$line'/ && a[$2]++
END {
for (i in a)   
   print a[i],i
}' in2.txt >> in3.txt
done < in-count2.txt

awk '{if( $1 ~ /^@/ ) {e = $1}
else
{split( $0, d, " " ) ; print e, d[1], d[2], d[3], d[4]}
}' in3.txt | awk '$2 == "1" {next} {print}' > in4.txt

#habillage
awk '{print $1,$2" fois "$3}' in4.txt | sed 's/@//g' | sort -r > in5.txt

#regrouper
awk 'BEGIN{FS=OFS=" "}
{a[$1]++ ; b[$1] = b[$1] " "$2" "$3" "$4" "$5" "$6}
END{ for( i in a )
print i,b[i]}
' in5.txt

#resultat
10  2 fois 4000  
11  3 fois 100   2 fois 300  

haut

Decouper un fichier en creant autant de fichiers que de colonnes


# in.txt
11 colonnes
2 lignes

#!/bin/bash
# nb caracteres maximum pour toutes les lignes
while read caract
do
echo ${#caract}
done < in.txt | sort -n | sed -n '$p' > out.txt

# lit tous les caracteres
limit=`cat out.txt`    
counter=1
until [ $counter -gt "$limit" ]
do
cat in.txt | cut -c ''$counter'-'$counter'' > cut-$counter  
let counter=counter+1
done

# resultat
fichier out.txt  ---> 11
# creation de 11 fichiers: cut-1 ; cut-2 ... cut-11
# contenu de cut-1
1
2

# contenu de cut-4
c
i

haut

Min et Max de valeurs placées sur une ligne


# in.txt                     # compteur.txt
1 902 993                    1
2 1003 1256 899 1000         2

# degrouper tous les champs (de 2 a 5) sur 1 seule colonne
awk '{
key=$1 ; $1="" ; n=split( $0, parties, "[ ]" );
for ( i=1; i<=n; i++ )
{if( length( parties[i] ) == 3 )
print ""key" 0"parties[i] ""      # valeurs a 4 digits
else
print ""key" "parties[i] ""}
}' in.txt | awk '{if ($2>0) print $0}' | sort > out1.txt

# out1.txt
1 0902
1 0993
2 0899
2 1000
2 1003
2 1256

# 1_script du minimum
if [ -e out-min.txt ] ; then rm out-min.txt ; fi
for i in `cat compteur.txt`
do
awk '{if( $1 == "'$i'" ) print $0}' out1.txt | head -1 >> out-min.txt
done

# resultat du minimum
1 0902
2 0899

# 2_script du maximum
if [ -e out-max.txt ] ; then rm out-max.txt ; fi
for i in `cat compteur.txt`
do
awk '{if( $1 == "'$i'" ) print $0}' out1.txt | tail -1 >> out-max.txt
done

# resultat du maximum
1 0993
2 1256

haut

Cumul de valeurs sur une ligne


# in.txt
line1 1 2 3
line2 4 5 6 7
line3 8 9 10

#!/bin/bash
awk 'BEGIN {FS=OFS=" "}
{ sum=0 ; n=0
for ( i=2; i<=NF; i++ )
{sum+=$i ; n++}
print $0,"sum:"sum," count:"n," avg:" sum/n
}' in.txt

# resultat
line1 1 2 3 sum:6 count:3 avg:2
line2 4 5 6 7 sum:22 count:4 avg:5.5
line3 8 9 10 sum:27 count:3 avg:9

haut

Supprimer un debut de fichier avant un pattern


# in.txt
1 fief toit
etre ville
toit eau

# supprimer le plus court 'debut-pattern'
#!/bin/bash
string=`cat in.txt`
echo "${string#*toit}"

# resultat
etre ville
toit eau

# supprimer le plus long 'debut-pattern'
#!/bin/bash
string=`cat in.txt`
echo "${string##*toit}"

# resultat
eau

haut

Supprimer une fin de fichier apres un pattern


# in.txt
1 fief toit
etre ville
toit eau

# supprimer le plus court 'pattern-fin'
#!/bin/bash
string=`cat in.txt`
echo "${string%toit*}"

# resultat
1 fief toit
etre ville

# supprimer le plus long 'pattern-fin'
#!/bin/bash
string=`cat in.txt`
echo "${string%%toit*}"

# resultat
1 fief

haut

Modifier les extremites d'une ligne avec "gsub" (bash)


# in.txt
data1 line1"
"data2 line2
"data3 line3"

#!/bin/bash
# deleter le debut des lignes
awk '{gsub( /^"/, "",$0 ) ; print}' in.txt |
# deleter la fin des lignes
awk '{gsub( /"$/, "",$0 ) ; print}'

# resultat
data1 line1
data2 line2
data3 line3

haut

Modifier une fin de ligne en retirant un caractere (bash)


#in.txt
123 data1@ data2 456@
789 data3@ 10 11
123 data4 data5 14@

#methode courte
#!/bin/bash
while read line;do echo ${line%@};done < in.txt  #delete la derniere occurrence

#methode longue
#!/bin/bash
while read line
do
#definir le dernier caractere comme pattern
a=`expr "$line" : '.*\(.\)'`
#condition sur le pattern
if [[ $a = "@" ]] ; then
#creer une variable = nombre de caracteres de la ligne -1 caractere
var=`expr ${#line} - 1`
#lire la ligne avec ce nouveau nombre de caracteres
b=`expr substr "$line" 1 $var`
echo $b
else
echo "$line"
fi
done < in.txt

#resultat
123 data1@ data2 456
789 data3@ 10 11
123 data4 data5 14

haut

Modifier une fin de ligne en ajoutant un caractere (bash)


#in.txt
123 data1@ data2 456@
789 data3@ 10 11
123 data4 data5 14@

#!/bin/bash
while read line
do
#definir le dernier caractere comme pattern
a=`expr "$line" : '.*\(.\)'`
#condition sur le pattern
if [[ $a = "@" ]] ; then
#creer la nouvelle ligne
echo $line"%"
else
echo "$line"
fi
done < in.txt

#resultat
123 data1@ data2 456@%
789 data3@ 10 11
123 data4 data5 14@%

haut

Modifier une fin de ligne en changeant un caractere (awk)


#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
T                                                            1

#####  1ere solution : utiliser "if"

awk '{
if(substr($0,80,1) == "0") {sub( ".$", "A" )} {print}
}' in.txt

#####  2eme solution : utiliser "la selection d'un pattern et sa negation"

awk '
$0 ~ /^R/  {gsub( /0$/, "A",$0 ) ; print}
$0 !~ /^R/ {print $0}
' in.txt

#####  3eme solution : utiliser "le tableau"

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 des 3 solutions
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
T                                                            1

haut

Modifier tout caractere en maitrisant sa position (awk)


# Technique de capture : if - else if - else

# in.txt
H0104 STREAMER DETAILS          MAL PORT STREAMER            1       0
H0105 OTHER DETAILS             OEX Outer STBD TAILBUOY      1           1
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
T                                                            1

awk '
{
# if ((length($0) != 80) && ($NF == 0)) {sub( ".$", "A" ) ; print}

if(substr($0,80,1) == "0") {sub( ".$", "A" ) ; print}
else if(substr($0,80,1) == "9") {a=substr($0,1,79) ; b=substr($0,80,1) ; b="J" ; print a""b}
else if((substr($0,62,1) == "1") && (substr($0,1,1) == "H")) {e=substr($0,1,61) ; f=substr($0,62,1) ; f="C" ; g=substr($0,63,17) ; print e""f""g}
# else if((substr($0,62,1) == "1") && ($0 ~ /^H/)) {e=substr($0,1,61) ; f=substr($0,62,1) ; f="C" ; g=substr($0,63,17) ; print e""f""g}
else
{print}
}

' in.txt

# resultat
H0104 STREAMER DETAILS          MAL PORT STREAMER            C       0
H0105 OTHER DETAILS             OEX Outer STBD TAILBUOY      C           1
R 283 487217.26818026.9     284 487229.76818026.3     285 487242.26818025.6    J
R 286 487254.66818025.0     287 487267.16818024.3     288 487279.66818023.7    J
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
T                                                            1

haut

Un signe en bout de ligne fait joindre la ligne qui suit (awk + getline)


#in.txt
data4
data5
data6\
data7

awk '{
line = $0
#print line
#print substr(line, length(line),1)
#print substr(line, 1, length(line)-1)

if (substr(line, length(line),1) == "\\")   # choisir ici le signe
i=getline
if (i > 0)
         {line = line" "$0}
         else
          {printf("missing continuation on line %d\n" , NR)}
     print line

}' in.txt | grep -v "missing continuation"

# resultat
data4
data5
data6\ data7

haut

Lire les 3 premiers caracteres de chaque ligne d'un fichier


# in.txt
123456
abcdef

#!/bin/bash
1_ methode en Bash
while read line
do
echo `expr "$line" : '\(...\)'`
done < in.txt

2_ methode en Awk
awk 'BEGIN{ FS=" "; OFS=" "}
{ if ( length($0) )
{ $0 = substr($0, 0, 3) }
else { $0 = "NA" }
print
}' in.txt

# resultat
123
abc

haut

Lire les 3 derniers caracteres de chaque ligne d'un fichier


# in.txt
123456
abcdef

#!/bin/bash
awk '{print substr( $0, length($0) - 2, length($0))}' in.txt

# resultat
456
def

haut

Effacer les 3 derniers caracteres de chaque ligne d'un fichier


# in.txt
123456789
abcdefghijk
line3 data123

#!/bin/bash
while read line
do
echo ${line::$((${#line}-3))}
done < in.txt

# resultat
123456
abcdefgh
line3 data

haut

En "AWK" : tester les tabulations cachees en fin de lignes


# tester les fins de lignes en "awk"
# tres utile pour deceler des tabulations cachees

# in.txt
data1
data2
data3/
data4	    # une tabulation se trouve ici

#!/bin/bash
pattern="\t"

awk '{
line = $0
{e = substr(line, length(line), 1)}
#print e
if(e == "'"$pattern"'") {print e,"<-- ok pattern ici"}
else
{print "no"}

}' in.txt > out.txt   # it's better to check the pattern in the file "out.txt"

# resultat
no
no
no
	 <-- ok pattern ici

haut

En "BASH" : tester les derniers caracteres en fin de lignes


# tester les fins de lignes en "bash"
# voit les derniers caracteres mais pas les tabulations de fin de lignes
# preferer employer "length" avec "awk"

#in.txt
data1
data2
data3/
data4	

#!/bin/bash
pattern="/"
n=1
while read line
do
   a=`expr "$line" : '.*\(.\)'`
   echo $a > tmp.txt

   if grep -q "$pattern" tmp.txt
      then echo "line : " $n " : ok pattern"
      else
      echo "line : " $n " : no pattern - code retour = " $?
   fi
let n=n+1
sleep 1
done < in.txt

# resultat
line :  1  : no pattern - code retour =  1
line :  2  : no pattern - code retour =  1
line :  3  : ok pattern
line :  4  : no pattern - code retour =  1

haut

Decouper un fichier a un pattern precis (le pattern est la fin du fichier decoupe)


# in.txt
Mr X
HSD
PIN = 12345
Mr Y
NGV
PIN = 45678

#!/bin/bash
awk 'BEGIN{ fn = "in1.txt" ; n = 1 }
{
print > fn
if ( substr($0, 1, 3) == "PIN" )   # "PIN" est la fin des fichiers
  { close (fn)
    n++
    fn = "in"n".txt"
  }
}' in.txt

# resultat
# in1.txt           # in2.txt
Mr X                Mr Y
HSD                 NGV
PIN = 12345         PIN = 45678

haut

Decouper un fichier a un pattern precis (le pattern est le debut du fichier decoupe)


# in.txt
Mr X
HSD
PIN = 12345
Mr Y
NGV
PIN = 45678

#!/bin/bash
awk '/^Mr X|^Mr Y/ {close("add_"f) ; f++}    # ecriture manuelle de tous les debuts de fichiers
{print $0 > "add_"f}' in.txt

# resultat
# add_1           # add_2
Mr X                Mr Y
HSD                 NGV
PIN = 12345         PIN = 45678

haut

Decouper un fichier a un pattern precis (autre exemple)


# in.txt
100 a b
200 c d
300 e f
400 g h

#!/bin/bash
# 1_ diviser automatiquement toutes les 3 lignes
awk '{ print > ("std_" int((NR+2)/3)) ".txt"}' in.txt

#resultat : 2 fichiers crees: std_1.txt ; std_2.txt

# 2_ diviser en triant sur le 1er digit d'une colonne:
awk '{print > substr($1,1,1)".txt"}' in.txt

#oubien :
cat in.txt | while read line
do
echo "$line" >> std_`echo $line | cut -c1`.txt
done

#resultat : 4 fichiers crees: std_1.txt ; std_2.txt ; std_3.txt ; std_4.txt

haut

Decouper un fichier d'apres la forme de sa fin de ligne


# in.txt
z-0061 5172-821 3665 
z-0061 5172-821 4754 
z-0061 @@@ @@@ 810, 942,
z-0061 1860, 2428,
z-0061 2813 
z-0061 @@@ @@@ 299, 303,
z-0061 515, 3880,
z-0061 4306 

# le but est de creer un fichier a chaque fois que la ligne ne se termine pas par une virgule
# donc dans cet exemple il y aura creation de 4 fichiers

#!/bin/bash
# toutes les lignes ne se terminant pas par une virgule, y coller le signe %% 
awk '$0 !~ /,$/ {print $0"%%"}
$0 ~ /,$/ {print}
' in.txt > inter1.txt

# preceder ce signe %% par un saut de ligne pour l'ecrire sur la ligne d'apres
sed 's/%%/\n%%/g' inter1.txt > inter2.txt

# supprimer le saut de ligne qui suit ce signe %%
sed -e :a -e '/%%$/N ; s_\n__ ; ta' inter2.txt > inter3.txt

# ajouter ce signe devant la 1ere ligne
awk 'NR==1 {print "%%"$0}
NR!=1 {print}' inter3.txt > inter4.txt

# coupe le fichier a la rencontre du signe %%
awk '
/^%%/{close("add_"f);f++}   # ne pas separer
{print $0 > "add_"f}
' inter4.txt

# resultat
add_1
%%z-0061 5172-821 3665

# add_2
%%z-0061 5172-821 4754

# add_3
%%z-0061 @@@ @@@ 810, 942,
z-0061 1860, 2428,
z-0061 2813

# add_4
%%z-0061 @@@ @@@ 299, 303,
z-0061 515, 3880,
z-0061 4306

haut

Inserer un trait au changement d'un pattern


# in.txt
10 data1
10
11 data2
11
12 data3
12

# 1- methode courte (en awk)

awk 'BEGIN{OFS=FS=" "}
{if ($1 != var )
   {var=$1;e="@"
   print $0,e}
   else
   print $0
}' in.txt | sed -e '/@/i\----------------' | sed 's/@//g'

###########################

# 2- methode longue (avec un tableau) (en awk)

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

###########################

# 3- avec une boucle while (en bash)

id2="z"
while read line
do
id=`echo $line | cut -d " " -f1`
[[ $id != $id2 ]] && id2=$id && echo "$line @" && continue
[[ $id == $id2 ]] && echo $line
done < in.txt | sed -e '/@/i\----------------' | sed 's/@//g'

###########################

# 4- avec une boucle for (en bash)

OLD_IFS=$IFS
IFS=$'\n'
id2="z"
for line in `cat in.txt`
do
id=`echo $line | cut -d " " -f1`
[[ $id != $id2 ]] && id2=$id && echo "$line @" && continue
[[ $id == $id2 ]] && echo $line
done | sed -e '/@/i\----------------' | sed 's/@//g'
IFS=$OLD_IFS

# resultat
10 data1
10
------------------
11 data2
11
------------------
12 data3
12
------------------

haut

Inserer une ligne avant des patterns listes dans un fichier


# fichier depart : FILE
data1
data2
pattern1
data3
data4
data5
pattern2
data6
data7
pattern3
data8
data9
pattern4
data10
data11

# fichier des patterns : PATTERN 
pattern1
pattern2
pattern3
pattern4

#!/bin/bash

############ 
############  parametres pour la marche manuelle
FILE=z-test-add-before.txt   # fichier depart

PATTERN=patterns.txt     # fichier des patterns

insert="@@@@@@@@"      # # ligne a inserer avant les patterns

AUTO=auto.sh

# changer 2 lignes (voir plus loin) dans la creation de $AUTO

############  fin des parametres pour la marche manuelle
############

variable=`cat $PATTERN`
set -- $variable
# 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 > tempw.txt  # fichier temporaire

# rendre visibles les variables a l'exterieur
while read line;do eval $line;done < tempw.txt > /dev/null

# nombre de lignes du fichier
total=`sed -n '$=' $FILE`
echo "nb lignes du fichier de depart : " $total

# deleter l'ancien script de commande
rm $AUTO
############################

# creation du script de commande : $AUTO
echo "#!/bin/bash" >> $AUTO
echo ""  >> $AUTO

echo "FILE=z-test-add-before.txt"  >> $AUTO          # changer ici manuellement
echo insert=\"@@@@@@@@\"  >> $AUTO                   # changer ici manuellement
echo "total=\"`sed -n '$=' $FILE`\"" >> $AUTO
echo "N=1" >> $AUTO
echo ""  >> $AUTO

echo "until [[ "\$N" -eq \$total ]]"  >> $AUTO
echo "do"  >> $AUTO
echo   "S1="\$N""  >> $AUTO
echo   "S2=\$(expr "\$N" + 1)"  >> $AUTO
echo   "N="\$S2""  >> $AUTO
echo   "VAL1=\$(sed -n \"\$S1 p\" \$FILE)"  >> $AUTO
echo   "VAL2=\$(sed -n \"\$S2 p\" \$FILE)"  >> $AUTO

# utilise le fichier des patterns comme ossature ($0) (et colle du texte avant et apres $0)
awk '
NR==1 {print "if [[ '\$VAL2' =~ \""$0"\" ]] ; then echo '\$VAL1'  ; echo $insert "} 
NR!=1 {print "elif [[ '\$VAL2' =~ \""$0"\" ]] ; then echo '\$VAL1'  ; echo $insert "}

' $PATTERN >> $AUTO

echo "else" >> $AUTO
echo "echo "\$VAL1"" >> $AUTO      # ne pas changer
echo "fi" >> $AUTO
echo  "sleep 1" >> $AUTO
echo "done" >> $AUTO

#################  fin de la creation de : $AUTO

# desactiver la commande suivante 'auto' pour executer la marche manuelle
bash $AUTO && exit

####################################

# marche manuelle :

N=1
until [ "$N" -eq $total ]
do

    S1=$N
    S2=`expr $N + 1`
    N=$S2
    VAL1=`sed -n "$S1 p" $FILE`
    VAL2=`sed -n "$S2 p" $FILE`

    if [[ $VAL2 =~ "$var1" ]] ; then echo $VAL1  ; echo $insert 
       elif [[ $VAL2 =~ "$var2" ]] ; then echo $VAL1 ; echo $insert 
       elif [[ $VAL2 =~ "$var3" ]] ; then echo $VAL1 ; echo $insert 
      elif [[ $VAL2 =~ "$var4" ]] ; then echo $VAL1 ; echo $insert 

    else
    echo $VAL1
    fi

    sleep 1
done 

# resultat :
data1
data2
@@@@@@@@
pattern1
data3
data4
data5
@@@@@@@@
pattern2
data6
data7
@@@@@@@@
pattern3
data8
data9
@@@@@@@@
pattern4
data10
data11

haut

Ajouter du texte sur une ligne ou apres une ligne


# in.txt
pattern
title1
data1
pattern
title2
data2

#!/bin/bash
# remplacer 'pattern' par '----------'
sed -e '/^pattern/ c\----------' in.txt > out1.txt
# ajouter '&&&' apres la ligne '---------'
sed -e '/----------/ a\&&& ' out1.txt > out2.txt
# supprimer le saut de ligne apres &&& pour coller les 2 lignes
sed '
/&&& /{
N
s/\n//
}' out2.txt > out3.txt

# resultat
----------
&&& title1
data1
----------
&&& title2
data2

haut

Inserer une ligne suivant un pattern


# in.txt
@
line2 data
line3 data
@
line5 data

#!/bin/bash
pattern="@"
while read line
do
echo "$line"
if [[ "$line" =~ "$pattern" ]]
then echo "----------"
fi
done < in.txt

# resultat
@
----------
line2 data
line3 data
@
----------
line5 data

haut

Inserer une ligne blanche selon un critere de longueur de ligne


# in.txt
data1 something1
data2

#!/bin/bash
maxlen=7
while read line
do
echo "$line"
len=${#line}
if [[ "$len" -gt "$maxlen" ]]
then echo      # insertion d'une ligne blanche
fi
done < in.txt
exit

# resultat
data1 something1

data2

haut

Memoriser une chaine de caracteres pour l'inserer sur une autre ligne


in.txt
@0066),(3063) 3201,3217,3233,3249,3265,3281,3297,3313,3329,3345
@0066),(3063) 3361,3377,3393,3409,3425,3441,3457,3473,3489,3505 
3521,3537,3553,3569,3585,3601,3617,3633,3649,3665,3681,3697,3713,3729,3745,3761,3777,3793,3809,3825)F
@0066),(2101) 2878,2894,2910,2926,2942,2958,2974,2990,3006,3022
@0066),(2101) 3038,3054,3070,3086,3102,3118,3134,3150,3166,3182 
3198)F

#!/bin/bash
awk -F " " '
$0 ~ /^@/  {e=$1} {print}
$0 !~ /^@/ {print e,$0}
' in.txt | grep "@" | sed 's/@/(/1' | sed 's/) /),(/1' 

#resultat
(0066),(3063) 3201,3217,3233,3249,3265,3281,3297,3313,3329,3345
(0066),(3063) 3361,3377,3393,3409,3425,3441,3457,3473,3489,3505 
(0066),(3063) 3521,3537,3553,3569,3585,3601,3617,3633,3649,3665,3681,3697,3713,3729,3745,3761,3777,3793,3809,3825)F
(0066),(2101) 2878,2894,2910,2926,2942,2958,2974,2990,3006,3022
(0066),(2101) 3038,3054,3070,3086,3102,3118,3134,3150,3166,3182 
(0066),(2101) 3198)F

haut

Capturer dans un fichier des patterns listes dans un 2eme fichier (exemple 1)


# file1    # =liste des patterns a capturer
capture1
capture3

# file2
line1 capture1 data1
line2 data2 1234 capture2
line3 data3 capture3
line4 capture4 data4

#!/bin/bash
if [ -e file3 ] ; then rm file3 ; fi
for i in `cat file1`
do
   while read col1 reste
   do
   var=`echo $reste | awk '$0 ~ /'$i'/ { print }'`
   echo $col1 $var
   done < file2 >> file3
done

# regroupement des lignes
awk 'BEGIN{FS=OFS=" "}
!arr[$1] {arr[$1] = $0 ; next}
{arr[$1] = arr[$1] " " $2 " " $3 " " $4}
END {for (i in arr) {print arr[i]}
}' file3

# resultat
line1 capture1 data1
line2 
line3 data3 capture3
line4 

haut

Capturer dans un fichier des patterns listes dans un 2eme fichier (exemple 2)


# file1    # =liste des patterns a capturer
capture1
capture3

# file2
line1 capture1 data1
line2 data2 1234 capture2
line3 data3 capture3
line4 capture4 data4

# 1 ere methode (en bash)

#!/bin/bash
for i in `cat file1`
do
awk -F" " -v x=$i '
{ for ( j=1; j<=NF; j++ )
if ( $j == x ) print}' file2
done

# 2 eme methode (en awk)

#!/bin/bash
awk '{ if (NF == 1)
arr[$0]=$0
else
for ( i in arr )
for ( j=1; j<=NF; j++ )
if ( $j == i )
print
}' FS=" " file1 file2

# resultat
line1 capture1 data1
line3 data3 capture3

haut

Modifier dans un fichier des patterns listes dans un 2eme fichier


# file.txt
a data1
b data2
c data3
d data4

# except.txt
a
c

# 1_ MODIFIER

#!/bin/bash
awk 'BEGIN{FS=" "}
FNR==NR {ex[$1]; next}
{ $2 = ($1 in ex) ? "0" : $2; print }
' except.txt file.txt

# resultat
a 0
b data2
c 0
d data4

# 2_ DELETER

#!/bin/bash
awk 'BEGIN{FS=" "}
FNR==NR {ex[$1]; next}
!($1 in ex)
' except.txt file.txt

# resultat
b data2
d data4

haut

Stopper la lecture d'un fichier à un pattern liste dans un 2eme fichier


# break.txt
STOP

# in.txt
line1 data1
line2 data2
STOP
line3 data3
line4 data4

#!/bin/bash
for i in `cat break.txt`
do
while read line ; do [[ "$line" =~ "$i" ]] && break ; echo $line ; done < in.txt
done

# resultat
line1 data1
line2 data2

haut

Capturer un pattern a une position fixe sur une ligne


# in.txt
123 data
12345 data

#!/bin/bash
egrep '^.{4}data' in.txt

# resultat
123 data

haut

Capturer un pattern avec un depart, une longueur et une arrivee


# file.txt
go beyond finishing line
what do you say ?
to have a share in doing something = contribuer a faire qqch

#!/bin/bash
sed -n '/in.\{3\}ing/p' file.txt

# resultat
go beyond finishing line
to have a share in doing something = contribuer a faire qqch

haut

Capturer la premiere occurrence d'une serie de lignes ayant meme pattern


# in.txt
100 first line data1
100 second line data2
101 first line data3
101 second line data4

#!/bin/bash
cat in.txt | sort -k1 | awk 'x !~ $1 ; {x = $1}'

# 2eme syntaxe
cat in.txt | sort -k1 | awk 'x[$1]++ {next} {print}'

# 3eme syntaxe
cat in.txt | sort -k1 | awk '!_[$1]++ {print $0; next} {next}'

# resultat
100 first line data1
101 first line data3

haut

Selectionner des lignes d'un fichier par des caracteres d'une colonne


# in.txt
"I came to realize the true meaning of life" 74
"The shoes came untied" 76
"his face went red" 80
"your wish will come true" 82
"Melons come from a vine" 97
"Understanding comes from experience" 99

#!bin/bash
# 1_selection des patterns
while read special
do
# selection de 2 caracteres et prendre le dernier a droite
var1=`echo ${special::2} | sed 's/.*\(.\)$/\1/' | awk '$0 ~ /[a-z]/ {print}'`  
echo $var1 
done < in.txt | grep "." > in-patterns.txt

# 2_lecture des patterns qui selectionneront les lignes
while read special
do
    while read minus
    do
    var2=`echo ${special::2} | sed 's/.*\(.\)$/\1/' | awk '$0 ~ /[a-z]/ {print}'`  
    if [[ $var2 = "$minus" ]] ; then echo $special ; fi
    done < in-patterns.txt
done < in.txt

# resultat
"his face went red" 80
"your wish will come true" 82

haut

Capture de lignes avec pattern de debut et de fin


in.txt
line1
data1
_start
data2
line5
_end
data3
line8
data4

#!/bin/bash
i=1
until [ $i -gt "10" ]
do
S=`grep -n "start" in.txt | awk -F":" '{print $1}'`
S=`expr $S + $i`
var=`sed -n "$S p" in.txt`
echo $var
if [[ $var =~ "end" ]] ; then break ; fi
let i=i+1
done

# resultat
data2
line5
_end

haut

Maitrise de la ligne et du champ pour reorganiser les champs


# in.txt
there's no harm in trying   il n'y a pas de mal a  essayer, on ne perd rien a essayer 
he got into trouble for stealing apples   il s'est fait attraper pour avoir vole des pommes 
the strain of making polite conversation   l'effort que ca demande de faire la conversation a  quelqu'un 
death finally released her from her suffering   la mort a mis un terme a ses souffrances 
they'll respond to the crisis by raising taxes   ils repondront a la crise en augmentant les impots 

##########################   parametres
LISTE=in.txt    # fichier entree a lire

##########################   fin des parametres

# deleter resultats precedents
rm out-*.txt

# nombre de lignes a lire
nbline=`awk '{print NR}' $LISTE | sed -n '$p'`   

# boucle sur les lignes
count=1    
until [ "$count" -gt $nbline ]
do
     # nb maxi de champs
     nbchampsmax=`awk '{print NF}' $LISTE | sort -n | sed -n '$p'`  # ;  echo $nbchampsmax

     # boucle sur les champs
     field=1
     until [ "$field" -gt "$nbchampsmax" ]
     do
     acount=`awk 'NR=='$count' {split( $0, d, " " ) ; if((d['$field'] ~ "ing") || (d['$field'] == "in") || (d['$field'] == "for") 
     || (d['$field'] == "before") || (d['$field'] == "of") || (d['$field'] == "by") || (d['$field'] == "from")) print NR" " d['$field']}' $LISTE | grep -v "something"`  
     echo $acount   >> out-"$count".txt     
     let field=field+1
     done     # fin boucle sur les champs

##################################
# info compteur de ligne
echo "line: " $count " / " $nbline
##################################

let count=count+1
done      # fin boucle sur les lignes

# ajouter zeros aux noms < 10
for i in `seq 1 9`
do
mv out-$i.txt out-00$i.txt
done   2>dev>null 

# ajouter zeros aux noms entre 10 et 99
for i in `seq 10 99`
do
mv out-$i.txt out-0$i.txt
done   2>dev>null 

# supprimer lignes vides
cat out-*.txt | grep "." > result1.txt

# reorganiser les champs de chaque ligne
# regrouper
awk 'BEGIN {FS=OFS=" "}
!a[$1] {a[$1] = $0;next}
{a[$1] = a[$1] " " $2 " " $3 " " $4}
END {for(i in a) {print a[i]}
}' result1.txt | sort -n | awk '{print $1,$2,$3}' > result2.txt

# classement par ordre alphabetique des verbes
cat result2.txt | awk '{print $0" @"}' > result3.txt

paste result3.txt $LISTE > result4.txt

# nettoyer
cat result4.txt | sort -k3 | awk '$0 ~ $3 {sub( /[),?!(]/, "" ) ; print}' > result5.txt

# retirer des parentheses
awk '$0 ~ $3 {sub( /[)]/, "" ) ; print}' result5.txt > result5a.txt

# separer les verbes par des traits (sed '/@/G' --> ajoute 1 ligne blanche)
awk '{ f[NR]=$3 ; g[NR]=$0 }
END {
for (i=1; i<=NR; i++)
if (f[i+1] != f[i])
{print "%"f[i],g[i]}
else
{print f[i],g[i]}
}' result5a.txt | sed '/%/G' | 
awk '
$0 ~ /^$/ {print "- - -------------------------------------"}    # noter les 2 espaces au debut des pointilles
$0 !~ /^$/ {print $0}' | awk '{$1 = "" ; print $0}' > result6.txt

# habillage
awk '{$1 = "" ; print $0}' result6.txt > result6a.txt
awk -F"@" '{printf ("%-23s %-23s\n",$1,$2)}' result6a.txt > result7.txt

# resultat: result7.txt
of making               the strain of making polite conversation   l'effort que ca demande de faire la conversation a  quelqu'un
-------------------------------------                        
by raising              they'll respond to the crisis by raising taxes   ils repondront a la crise en augmentant les impots
-------------------------------------                        
for stealing            he got into trouble for stealing apples   il s'est fait attraper pour avoir vole des pommes
-------------------------------------                        
from suffering          death finally released her from her suffering   la mort a mis un terme a ses souffrances
-------------------------------------                        
in trying               there's no harm in trying   il n'y a pas de mal a essayer ; on ne perd rien a essayer
-------------------------------------                        

haut

Marquer des groupes de patterns semblables (exemple simple)


# in.txt                      # in2.txt
100 first line data1          100 1
100 second line data2         101 2
101 first line data3
101 second line data4

# 1ere methode (avec 1 seul fichier)
awk '{if( $1 != var )
{var = $1 ; count++}
print $0, count}
' in.txt

# 2eme methode (avec 2 fichiers)
awk 'NR==FNR {arr[$1]=$2 ; next}
{print $0, arr[$1]}
' in2.txt in.txt

# resultat
100 first line data1 1
100 second line data2 1
101 first line data3 2
101 second line data4 2

haut

Marquer des groupes de patterns semblables (exemple plus complique)


# test.txt
#100 data 33 11
#100 data 33 11
#100 data 33 12
#100 data 33 12
#100 data 34 13
#100 data 34 13
#100 data 34 14
#100 data 34 14
#100 data 34 14
#101 data 74 15
#101 data 74 15
#101 data 74 16
#101 data 74 16
#2 data2

awk '{
if ( substr($0,1,1) == "1" ) 
      {
          if (substr($0,1,3)  != first)  {n = 0 }
          if (substr($0,10,2)  != second)     {n = 0 }
          if (substr($0,13,2)  != third) {n++}
              
          {
          first = substr($0,1,3) 
          second = substr($0,10,2)
          third = substr($0,13,2)
          }
          
          { print $0,n }
           
      }
else
{
if (substr($0,1,1) == "2")  {print $0} 
}
}' test.txt
# resultat
#100 data 33 11 1
#100 data 33 11 1
#100 data 33 12 2
#100 data 33 12 2
#100 data 34 13 1
#100 data 34 13 1
#100 data 34 14 2
#100 data 34 14 2
#101 data 74 15 1
#101 data 74 15 1
#101 data 74 16 2
#101 data 74 16 2
#2 data2

haut

Coller des valeurs a un pattern (exemple 1)


# a.txt
ALL   001  3  4
5     001  6  7
ALL   002  8  9
10    002  11 12

# b.txt
001   2027-2145
002   1820-1967

#!/bin/bash
awk 'NR==FNR { f[$1]=$2 ; next } /^ALL/ { print f[$2],$2,$3,$4 ; next }1' b.txt a.txt

# resultat
2027-2145   001  3  4
5           001  6  7
1820-1967   002  8  9
10          002  11 12

haut

Coller des valeurs a un pattern (exemple 2)


# filea.txt
5:John
4:Michel
9:Rachel

# fileb.txt
9
4
5
4
22

#!/bin/bash
cat fileb.txt | while read num
do
NAME=`awk -F ":" '$1=="'"$num"'" {print '$num' FS $2}' filea.txt`
[ -z $NAME ] && echo "$num":"NO MATCH FOUND" || echo $NAME
done

# resultat
9:Rachel
4:Michel
5:John
4:Michel
22:NO MATCH FOUND

haut

Coller des valeurs a un pattern (exemple 3)


# file1.txt
alex id23
aina id12
ciam id13
alot id34
brian id64

# file2.txt
id13 new1
id12 new2
id64 new3

# 1ere methode
#!/bin/bash
awk 'BEGIN{FS=" "}
NR==FNR{arr[$2]=$0 ; next}
$1 in arr && $0=arr[$1] FS $2
' file1.txt file2.txt

# 2eme methode
#!/bin/bash
awk 'BEGIN{FS=" "}
NR==FNR{arr[$1]=$2 ; next}
$2 in arr{print $0, arr[$2]}
' file2.txt file1.txt

# resultat
ciam id13 new1
aina id12 new2
brian id64 new3

haut

Un titre de paragraphe devient marqueur (en utilisant 'split')


# in.txt
entry one
100 first line data1
100 second line data2
entry two
101 first line data3
101 second line data4

#!/bin/bash
awk '{if( $1 == "entry" ) {e = $2}
else
{split( $0, d, " " ) ; print e, d[1], d[2], d[3], d[4]}
}' in.txt

# resultat
one 100 first line data1
one 100 second line data2
two 101 first line data3
two 101 second line data4

haut

Un titre de paragraphe devient marqueur (sans utiliser 'split')


# in.txt
@ accept
data
3line
@ agree
data
line6
@ believe
3data
9line

#!/bin/bash
awk '{
if($0 ~ /^@/) {e=$0 ; print substr(e,1,3),e}
else
{print}
}' in.txt | sed 's/@ /@/1' | sed 's/@/***/1' > inter.txt

awk '$1 ~ /\*\*\*a/ {i=i+1} {print $0,i}' inter.txt  |
awk '!a[$NF]++  {print $0 ; next} { sub($NF, "") ; print }' | sed 's/^ //g'

# resultat
***a @ accept 1
data
3line
***a @ agree 2
data
line6
***b @ believe
3data
9line

haut

Un champ d'une ligne devient titre de la ligne (sans utiliser 'split')


# FILE :
line1 data1 string
line2
line3 data2
line4 data3 pattern
line5
line6 data4
line7 data5 data
line8
line9 data6
end end end

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

FILE=in.txt
OUT=out.txt
# ajouter 1 ligne a la fin (manuellement) : end end end
# faire manuellement si pas possible en automatique
PATTERNS=in-patterns.txt   

############################# fin des parametres
# fichiers des patterns en automatique
awk '{print $3}' $FILE | grep "." > $PATTERNS

# deleter actions precedentes
rm $OUT

# script
N=1
# nombre de lignes du fichier des patterns
total=`sed -n '$=' $PATTERNS`
until [ "$N" -eq $total ]
do
S1=$N
S2=`expr $N + 1`
N=$S2
VAL1=`sed -n "$S1 p" $PATTERNS`
VAL2=`sed -n "$S2 p" $PATTERNS`
echo $VAL1 ; echo $VAL2 ; echo

   while read line
   do
   set -- $line

   if [[ "$3" == "$VAL1" ]] ; then w1=`echo $3` ; echo $w1 $line | awk '{if($NF = "$VAL1") {$NF=""} {print}}'  ; fi

   if [[ "$3" != "$VAL1" ]] && [[ "$3" != "$VAL2" ]] ; then echo $w1 $line  ;   fi

   if [[ "$3" == "$VAL2" ]] ; then  exit ; fi

   done < $FILE | grep "^$VAL1"  >> $OUT       # boucle dans $FILE

done     # boucle dans $PATTERNS

# resultat : $OUT
string line1 data1 
string line2
string line3 data2
pattern line4 data3 
pattern line5
pattern line6 data4
data line7 data5 
data line8
data line9 data6

haut

Occurrences d'un pattern


Recherche sur la lettre "a"

# in.txt
a data-one.txt
a data-two.txt
a data-three.txt
b data-four.txt
b data-five.txt

#!/bin/bash
awk '$1 ~ /a/ { i=i+1 } END {print i}' in.txt

# resultat
3

haut

Marquer les numeros des occurrences a partir d'une liste de patterns


# pattern.txt
a
b

# in.txt
a data-one.txt
a data-two.txt
a data-three.txt
b data-four.txt
b data-five.txt

#!/bin/bash
# deleter les actions precedentes
if [ -e out.txt ] ; then rm out.txt ; fi

for j in `cat pattern.txt`
do
awk '$1 ~ /'$j'/ {i=i+1} {print $0,i}' in.txt |
awk '!f[$NF]++ {print $0 ; next} {sub($NF, "") ; print}' |
awk '$NF !~ /t/ {print}' >> out.txt
done

# out.txt
a data-one.txt 1
a data-two.txt 2
a data-three.txt 3
b data-four.txt 1
b data-five.txt 2

haut

Deleter les occurrences repetees dans une colonne, et ne garder que la 1ere


# in.txt
a data-one.txt
a data-two.txt
a data-three.txt
b data-four.txt
b data-five.txt

#!/bin/bash
awk -F" " '!f[$1]++ {print $0 ; next}
{sub( $1, "" ) ; print}' in.txt

# resultat
a data-one.txt
  data-two.txt
  data-three.txt
b data-four.txt
  data-five.txt

haut

Occurrences d'un caractere dans plusieurs fichiers


# fichier  z1.txt
data1
data2
123 234 3451 456 567 678 7891
123 234 0001 456 567 555 7891
123 234 9991 456 567 666 7891
123 234 8881 456 567 777 7891
123 234 7771 456 567 888 7891
123 234 6661 456 567 999 7891

# fichier  z2.txt
data3
data4
124 234 3452 457 567 672 7890
124 234 0002 457 567 552 7890
124 234 9992 457 567 662 7890
124 234 8881 457 567 772 7890
124 234 7771 457 567 882 7890
124 234 6661 457 567 992 7890
 
# capture du 4eme caractere de la colonne 3
for i in `ls z*.txt`
do
awk '{print substr($3,4,1)}' $i>y-$i
done

# supprimer les lignes vides
for i in `ls y-z*.txt`
do
sed '/^$/d' $i > x$i
done

# frequence du caractere
for j in `ls xy-z*.txt`
do
   awk '{
   for (i=1; i<=NF; i++)
   mot[$i]++        # mot[$i]=mot[$i]+1
   }
   END {
   for (i in mot)
   print i " -->",mot[i]" occurrences"
   }' $j > v$j
done

# marquer nom du fichier devant chaque ligne
for i in vxy-z*.txt
do
seq=`ls $i  | cut -c5-10`
awk '{print seq" : ",$0}' seq=${seq} $i
echo "----"
done

# resultat

z1.txt :  1 --> 6 occurrences
----
z2.txt :  1 --> 3 occurrences
z2.txt :  2 --> 3 occurrences
----

haut

Incrementer des lignes consecutives de format identique, le compteur est mis a zero ensuite


# in.txt
title1
 sentence one
 sentence two
 sentence three
   [example 1]
title2
 sentence four
 sentence five
title3
   [example 2]

#!/bin/bash
# ajouter un signe devant les lignes qu'on veut incrementer
sed 's/^ [a-z]/%% &/g' in.txt > inter1.txt

# incrementer les consecutives ; remettre a zero ensuite
awk '{
if($0 ~ /^%%/) {i=i+1} {print i,$0}
if($0 !~ /^%%/) {i=""}
}' inter1.txt | awk '($0 ~ /^[1-9]/) && ($1 ~ /[1-9]/) && ($2 !~ /%%/) {$1=""} {print}'

# resultat 
 title1
1 %%  sentence one
2 %%  sentence two
3 %%  sentence three
 [example 1]
 title2
1 %%  sentence four
2 %%  sentence five
 title3
    [example 2]

haut

Joindre un signe avec la ligne suivante (exemple 1)


# in.txt
data 123:
line2
data 456:
line4

sed -e :a -e '/:$/N ; s_\n__ ; ta' in.txt | sed 's/:/ /g'

# resultat
data 123 line2
data 456 line4

haut

Joindre un signe avec la ligne suivante (exemple 2)


# in.txt
data 123:
line2
data 456:
line4

awk '{
while ( $0 ~ /\:$/ )
{getline record
$0 = $0 " " record}
print $0
}' in.txt | sed 's/://g'

# resultat
data 123 line2
data 456 line4

haut

Joindre un signe avec la ligne suivante (exemple 3)(awk + getline)


#in.txt
data4
data5
data6\
data7

awk '{
line = $0
#print line
#print substr(line, length(line),1)
#print substr(line, 1, length(line)-1)

if (substr(line, length(line),1) == "\\")    # choisir ici le signe
i=getline
if (i > 0)
         {line = line" "$0}
         else
          {printf("missing continuation on line %d\n" , NR)}
     print line

}' in.txt | grep -v "missing continuation"

# resultat
data4
data5
data6\ data7

haut

Joindre un signe au bout de la ligne precedente (exemple 1)


# in.txt
data 123
=line2
data 456
=line4
=line5

sed -e :a -e '$!N ; s/\n=/ / ; ta' -e 'P;D' in.txt

# resultat
data 123 line2
data 456 line4 line5

haut

Joindre un signe au bout de la ligne precedente (exemple 2)


# in.txt
data 123
=line2
data 456
=line4
=line5

awk 'END { print r }
r && !/^=/ { print r ; r = "" }
{ r = r ? r $0 : $0 }
' in.txt | sed 's/=/ /g'

# resultat
data 123 line2
data 456 line4 line5

haut

Joindre un signe au bout de la ligne precedente sauf si cette derniere se termine par @ (exemple 3)


# in.txt
data 123
=line2
data 456@
=line4
=line5

awk 'END { print r }
r ~ /@$/ || !/^=/ { print r ; r = "" }
{ r = r ? r $0 : $0 }
' in.txt | sed 's/=/ /g' | sed 's/^ //g'

# resultat
data 123 line2
data 456@
line4 line5

haut

Les lignes qui commencent par un signe collent les suivantes a leur fin si elles ne possedent pas ce signe


# in.txt (ajouter un blanc a la fin des lignes)
data 123
@line2
@data 456
line4
line5

awk 'NR > 1 && /^@/ {print ""}
{printf $0}
END {print ""}
' in.txt

# resultat
data 123 
@line2 
@data 456 line4 line5 

haut

Printer les lignes du fichier2 qui manquent dans le fichier1


# ina.txt
accept
access
accomplish
accumulate

# inb.txt
accept
access
accommodate
accomplish
accord
accumulate

#!/bin/bash
comm -23 inb.txt ina.txt  2>dev

# resultat
accommodate
accord

haut

Comparer 2 fichiers : identiques ou differents


#!/bin/bash

# a.txt
data1
data2

# b.txt
data1
data2
data3

if cmp a.txt b.txt  &> /dev/null
then echo "a et b identiques"
else echo "a et b differents"
fi

# resultat
a et b differents

haut

Intersection de 2 fichiers : lignes uniques et communes



# PREREQUIS : verifier que les fichiers a comparer ne comportent pas
# la sequence suivante : "      >" car elle provoquera une erreur dans le script.

# in1.txt
keep me advised of your progress
these problems are currently being investigated
until further notice
i visit him less than i should

# in2.txt
keep me advised of your progress
a lot of people are addicted to sugar
until further notice
the hectic pace of everyday life
we are relying on good weather

#!/bin/bash
ARGS=2    # 2 arguments attendus par le script
E_MAUVAISARGS=65
E_ILLISIBLE=66

if [ $# -ne "$ARGS" ]
then
echo "usage: `basename $0` fichier1 fichier2"
exit $E_MAUVAISARGS
fi

if [[ ! -r "$1" || ! -r "$2" ]]
then
echo "les 2 fichiers a comparer doivent etre lisibles"
exit $E_ILLISIBLE
fi

# lignes uniques de chaque fichier
diff --side-by-side <(sort $2) <(sort $1) | egrep "      >|     \|" | sed 's_      >_@@@@@_g' | 
sed 's_      |_@@@@@_g' | sed 's_\(.*\)\(@@@@@\)\(.*\)_\3_g' | sed 's/\t//g' | awk '{print "lignes uniques a '$1': "$0}' > tmp1.txt
diff --side-by-side <(sort $1) <(sort $2) | egrep "      >|     \|" | sed 's_      >_@@@@@_g' | 
sed 's_      |_@@@@@_g' | sed 's_\(.*\)\(@@@@@\)\(.*\)_\3_g' | sed 's/\t//g' | awk '{print "lignes uniques a '$2': "$0}' >> tmp1.txt

# lignes communes
comm <(sort $1) <(sort $2) | awk '$0 ~ /^\t\t/ {print}' | sed 's/\t\t/lignes communes: /g' >> tmp1.txt

# habillage
grep "lignes uniques a "$1":" tmp1.txt | wc -l | awk '{print "    _ "$0" lignes uniques a '$1':"}' > tmp2.txt
cat tmp1.txt | grep "lignes uniques a "$1":" | sed 's/lignes uniques a '$1': //g' >> tmp2.txt
echo >> tmp2.txt
grep "lignes uniques a "$2":" tmp1.txt | wc -l | awk '{print "    _ "$0" lignes uniques a '$2':"}' >> tmp2.txt
cat tmp1.txt | grep "lignes uniques a "$2":" | sed 's/lignes uniques a '$2': //g' >> tmp2.txt
echo >> tmp2.txt
grep "lignes communes:" tmp1.txt | wc -l | awk '{print "    _ "$0" lignes communes:"}' >> tmp2.txt
cat tmp1.txt | grep "lignes communes:" | sed 's/lignes communes: //g' >> tmp2.txt
cat temp2.txt

# resultat
    _ 2 lignes uniques a in1.txt
i visit him less than i should
these problems are currently being investigated

    _ 3 lignes uniques a in2.txt
a lot of people are addicted to sugar
the hectic pace of everyday life
we are relying on good weather

    _ 2 lignes communes
keep me advised of your progress
until further notice

haut

Un titre de paragraphe est capture a un pattern


# in.txt
entry 1
data1

entry 2
data2

#!/bin/bash
# 1ere syntaxe  ( capture du titre de paragraphe )
awk '/^entry/ {cnt=1} cnt -- > 0' in.txt

# 2eme syntaxe  ( capture de la ligne blanche avant le titre )
awk 'NR==1 || cnt -- > 0 ; /^$/ {cnt=1}' in.txt

# resultat
entry 1
entry 2

haut

Operations entre lignes 'n+1' et 'n'


# in.txt
10
30
100
10

#!/bin/bash
FILE=in.txt
N=1
# nombre de lignes du fichier
total=`sed -n '$=' $FILE`
until [ "$N" -eq $total ]
do
S1=$N
S2=`expr $N + 1`
N=$S2
VAL1=`sed -n "$S1 p" $FILE`
VAL2=`sed -n "$S2 p" $FILE`
expr $VAL2 - $VAL1
done

# resultat
20
70
-90

haut

Supprimer des caracteres entre 2 bornes connues


# in.txt
<gpx>123<cmp>data1</cmp></gpx>
<gpx>456<cmp>data2</cmp></gpx>
#       ^^^^^^^^^^^^^^^^        partie a supprimer

while read line
do
echo $line | sed 's_\(.*\)\(<cmp>\)\(.*\)\(</cmp>\)\(.*\)_\1\5_'
#                           ^^^^^          ^^^^^^
#                      1      2       3       4       5
done < in.txt

#resultat
<gpx>123</gpx>
<gpx>456</gpx>

haut

Suppression de lignes doubles


# in.txt
data1
line
data2
line

#!/bin/bash
awk '!x[$0]++' in.txt

# resultat
data1
line
data2

haut

Derniere modification : Fevrier 2013