Recherche et tri

Sommaire

Index

Recherche et classement de données sous UNIX / Linux

Préparation du TP

Dans cette partie, les manipulations se font dans le dossier tpfichiers créé au chapitre précédent.

Exécuter le script init depuis le dossier premiersPas afin de recréer les fichiers temporaires.

Se replacer ensuite dans le dossier tpfichiers

Manipulations

Récupérer les fichiers suivants depuis donnees-linux.tar.gz : 2050.txt, nblng10.txt, tp2.txt et notes.txt

Pour plus d’informations sur la commande tar, voir ce document.

  1. Lister les lignes du fichier 2050.txt contenant le chiffre 1
  2. Lister les lignes du fichier 2050.txt contenant le chiffre 1 ou le chiffre 5
grep -E '1|5' 2050.txt
grep -e 1 -e 5 2050.txt
grep '[15]' 2050.txt
  1. Modifier cette commande afin de faire apparaître au début de chaque ligne le numéro de la ligne correspondante dans le fichier d’origine

Ajouter le commutateur -n

  1. Listez le fichier tp2.txt en faisant précéder chaque ligne par son numéro dans le fichier.
  2. Renommer le fichier tp2.txt en tp2resultat.txt
  3. Revenir à la racine de votre répertoire utilisateur ($HOME) et lister tous les fichiers de votre espace de travail avec leurs attributs complets
  4. Rechercher le fichier nommé tp2resultat.txt
find . -name tp2resultat.txt
  1. Rechercher dans le dossier /etc tous les fichiers dont le nom contient net
find /etc -name '*net*'
  1. Utiliser cette même commande pour afficher ces fichiers entre les caractères @ et % (par exemple afficher: @/etc/networks%)
find /etc -name '*net*' -exec echo @{}% ';'

#ou
find /etc -name '*net*' -exec echo @{}% \;
  1. Utiliser cette même commande pour afficher les lignes de ces fichiers contenant le chiffre 1 ou le chiffre 7
find /etc -name '*net*' -exec grep [17] {} ';'
find /etc -name '*net*' | xargs -i grep [17] {}
  1. Ajouter à l’affichage le fichier dans lequel a été trouvée la ligne
find /etc -name '*net*' -exec grep -H [17] {} ';'
  1. Faites en sorte que la casse (différence majuscule/minuscule) soit ignorée durant la recherche
find /etc -name '*net*' -exec grep -iH dhcp {} ';'
  1. En utilisant la même commande afficher toutes les lignes des fichiers tp2resultat.txt et 2050.txt contenant le nombre 15 ou la chaîne err
find . -name '*2*.txt' -exec grep -iHnE '1|er' {} \;

find . \( -name 'tp2resultat.txt' -o -name '2050.txt' \) -exec grep -iHn -e 'err' -e 15 {} ';'

Voir aussi la section Operators du manuel de find

xargs

Alternatives avec xargs (effet similaire à l’utilisation du commutateur -exec):

find . -name 'tmp*' |xargs grep je
find . -name 'tmp*' |xargs grep -n je
find . -name 'tmp*' |xargs -i grep je {} /dev/null
find . -name 'tmp*' |xargs -i grep -H je {}
find . -name 'tmp*' |xargs grep -in je

Pour effectuer une recherche depuis un terminal, voici les commandes à privilégier.

Recherche sensible à la casse

find . -name '*nom_fichier*' | xargs -i grep -H chaine_cherchee {}

Recherche non-sensible à la casse

find . -name '*nom_fichier*' | xargs -i grep -iH chaine_cherchee {}

Recherche non-sensible à la casse avec affichage de numéros de lignes

find . -name '*nom_fichier*' | xargs -i grep -iHn chaine_cherchee {}

Sous macOS, à la place de -i, utiliser -I{}

Opérateurs logiques avec find

# Trouver les fichier qui sont des dossiers
$ find . -name 'tmp*' -a -type d
./exemple/tmp.ZkBCkHmLkO.info
./exemple/tmp.cmdAiFEBba.info
./exemple/tmp.info

# Trouver des fichiers qui ne sont pas des dossiers (! = négation)
$ find . -name 'tmp*' -a ! -type d
./exemple/tmp.FciU1n470h.info
./exemple/tmp.VvqaJQUb5H.info
./exemple/tmp.gFZoBzMDjG.info
./exemple/tmp.puTL1nVAO3.info
./exemple/tmp.c1M7jij4DQ.info
./exemple/tmp.6UMHo8OaV1.info

Lignes vides et lignes blanches

Pages de manuel

Sous Debian et dérivés

Voir la page de manuel re_format

Sous RedHat/CentOS et dérivés

Voir la page de manuel 7 regex:

man 7 regex

Quelques exemples d’expressions régulières étendues

On utilise le commutateur -E de la commande grep.

Pour afficher la lettre e ou E suivie d’une ou plusieurs lettres quelconques.

grep -E "[eE]\w+" nblng10.txt
grep -E "^[Ee]" nblng10.txt
grep -E "[Ee]$" nblng10.txt
grep -E "[Ee]*$" nblng10.txt
grep -E "h[Ee]*$" nblng10.txt

Affichage des espaces

grep -E “[[:space:]]” nblng10.txt grep -E “” nblng10.txt

Exercices

  1. Dans le fichier nblng10.txt, sur combien de lignes le mot Nibelung apparaît-il ?
  2. Afficher le contenu du fichier nblng10.txt en éliminant les lignes vides et mettre le résultat dans nblng10bis.txt
  3. Extraire les lignes ne contenant que des blancs (espaces ou tabulations) et mettre le résultat dans nblng10ter.txt

Expressions standards

# 0 ou plusieurs espaces
grep -v '^[[:space:]]*$' nblng10.txt
# ou
grep '^[[:space:]]\{0,\}$' nblng10.txt
# 1 ou plusieurs espaces
grep -v '^[[:space:]]\+$' nblng10.txt
# 1 ou plusieurs espaces
grep '^[[:space:]]\{1,\}$' nblng10.txt
# 0 fois exactement
grep '^[[:space:]]\{0\}$' nblng10.txt

Expressions régulières étendues

$ grep -E '^\s+$' nblng10.txt
  1. Combien y a-t-il de lignes blanches ?
grep '^[[:space:]]*$' nblng10.txt | wc -l

Exemple de filtrage d’un tableau

$ cat tableau.csv
C1;C2;C3
1;2;3
a;b;c
C1;C2;C3;C4
1;2;3;4
a;b;c;d

$ grep -E '^[^;]*;[^;]*;[^;]*$'
^C
$ grep -E '^[^;]*;[^;]*;[^;]*$' tableau.csv
C1;C2;C3
1;2;3
a;b;c
$ grep -E '^[^;]*;[^;]*;[^;]*;[^;]*$' tableau.csv
C1;C2;C3;C4
1;2;3;4
a;b;c;d
$ nano tableau.csv
$ grep -E '^[^;]*;[^;]*;[^;]*;[^;]*$' tableau.csv
C1;C2;C3;C4
1;;3;4
a;b;;d
$ grep -E '^([^;]*;){2}[^;]*$' tableau.csv
C1;C2;C3
1;2;3
a;b;c
$ grep -E '^([^;]*;){1}[^;]*$' tableau.csv

Début et fin de fichiers

Exemple : head -3 notes.txt | tail -2 permet d’extraire les 2e et 3e lignes du fichier notes.txt

A partir du fichier notes.txt, écrivez les traitements suivants, en utilisant les commandes cut et sort :

  1. Afficher la liste des étudiants de la licence informatique triée par ordre alphabétique des nom et prénom.
head -1 notes.txt ; tail -n +2 notes.txt | sort -k 1,1 -k 2,2
  1. Afficher les résultats de LIN2 par ordre croissant des notes. En cas d’égalité, les étudiants sont rangés par ordre alphabétique des nom et prénom.
head -1 notes.txt ; tail -n +2 notes.txt | sort -k 4,4n -k 1,1 -k 2,2

Ici, vous pouvez utiliser la commande tr :

  1. Prendre le contenu du fichier nblng10.txt et le mettre en majuscules dans le fichier nblng10maj.txt
cat nblng10.txt | tr 'a-z' 'A-Z'
cat nblng10.txt | tr '[a-z]' '[A-Z]'

La commande sort

Les exemples ci-dessus sont un peu “surdimensionnés”.

Voici quelques exemples plus simples d’utilisation de la commande sort:

$ echo 1 1 23 3 4 5 8 8 9 0 23 56 7890 | xargs -n 1
1
1
23
3
4
5
8
8
9
0
23
56
7890

Classement alphabétique:

$ echo 1 1 23 3 4 5 8 8 9 0 23 56 7890 | xargs -n 1 | sort
0
1
1
23
23
3
4
5
56
7890
8
8
9

Classement numérique:

$ echo 1 1 23 3 4 5 8 8 9 0 23 56 7890 | xargs -n 1 | sort -n
0
1
1
3
4
5
8
8
9
23
23
56
7890

Classement numérique et suppression des doublons:

$ echo 1 1 23 3 4 5 8 8 9 0 23 56 7890 | xargs -n 1 | sort -n -u
0
1
3
4
5
8
9
23
56
7890

Manipulation de masses

Renommage de masse

supv@debian12:~$ cd tpfichiers/
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz
./
./2050.txt
./nblng10.txt
./notes.txt
./tp2.txt
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz | xargs echo rm
rm ./ ./2050.txt ./nblng10.txt ./notes.txt ./tp2.txt
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz | grep './$'
./
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz | grep -v './$'
./2050.txt
./nblng10.txt
./notes.txt
./tp2.txt
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz | grep -v './$' | xargs echo rm
rm ./2050.txt ./nblng10.txt ./notes.txt ./tp2.txt
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz | grep -v './$' | xargs echo mv 
mv ./2050.txt ./nblng10.txt ./notes.txt ./tp2.txt
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz | grep -v './$' | xargs -n 1 echo mv 
mv ./2050.txt
mv ./nblng10.txt
mv ./notes.txt
mv ./tp2.txt
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz | grep -v './$' | xargs -i echo mv {} {}.toto
mv ./2050.txt ./2050.txt.toto
mv ./nblng10.txt ./nblng10.txt.toto
mv ./notes.txt ./notes.txt.toto
mv ./tp2.txt ./tp2.txt.toto
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz | grep -v './$' | xargs -i echo mv {} {}.toto^C
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz | grep -v './$' | xargs -i echo mv {} $(echo {} | sed s/\.txt/.toto/)
mv ./2050.txt ./2050.txt
mv ./nblng10.txt ./nblng10.txt
mv ./notes.txt ./notes.txt
mv ./tp2.txt ./tp2.txt
supv@debian12:~/tpfichiers$ for f in $(tar tf donnees-linux.tar.gz) ; do echo mv $f ${f%.txt}.toto ; done
mv ./ ./.toto
mv ./2050.txt ./2050.toto
mv ./nblng10.txt ./nblng10.toto
mv ./notes.txt ./notes.toto
mv ./tp2.txt ./tp2.toto
supv@debian12:~/tpfichiers$ tar tf donnees-linux.tar.gz | grep -v './$' | xargs -i bash -c 'echo mv {} $(echo {} | sed s/\.txt/.toto/)'
mv ./2050.txt ./2050.toto
mv ./nblng10.txt ./nblng10.toto
mv ./notes.txt ./notes.toto
mv ./tp2.txt ./tp2.toto
supv@debian12:~/tpfichiers$ 

Autre solution avec sed

ls | grep \.png$ | sed 'p;s/\.png/\.jpg/' | xargs -n2 mv