Outils de base de traitement du texte
Ce chapitre expose les notions et les outils de base pour traiter du texte sous Linux. On s’attachera aux notions de tubes et de redirections d’entrée et de sortie et leur interaction avec différents binaires POSIX comme cat, tac, head, tail, tee, wc, split, od, hexdump, cut, uniq, sort, paste, join, fmt, pr, tr et diff.
1. Redirections et tubes
https://wiki.bash-hackers.org/syntax/redirection
1.1. Redirections et tubes
Les processus UNIX ouvrent trois descripteurs de fichiers standards (correspondant aux flux standards) qui permettent de traiter les entrées et sorties. Ces descripteurs standards peuvent être redéfinis pour chaque processus. Dans la plupart des cas, le descripteur stdin (entrée standard) est le clavier, et les deux descripteurs de sortie, stdout (sortie standard) et stderr (l’erreur standard), sont l’écran.
Un processus et ses 3 descripteurs de fichiers STDIN (0), STDOUT (1) et STERR (2)
STDIN < ------ PROCESSUS ---- >
| ---- >> STDOUT
| ---- |
|
2>
STDERR
1.2. Redirection de l’entrée standard
programme < fichier
Dans ce cas, les données vont de droite à gauche. L’opérateur “<
” ne peut être utilisé qu’avec stdin : on ne peut pas l’utiliser avec les flux de sortie.
Si le fichier contient les instructions l et q (une instruction par ligne), alors dans l’exemple suivant fdisk affichera la table des partitions de /dev/sda
, puis affichera l’aide puis quittera :
cat > fdisk.txt
l
q
[CRTL-D]
su
fdisk /dev/?da < fdisk.txt
exit
Redirection de l’entrée standard :
PROCESSUS ---- < ---- FICHIER / PÉRIPHÉRIQUE
---- 0< ----
1.3. Etiquettes
Une étiquette permet de limiter la redirection. C’est utile par exemple pour donner des arguments à une commande sur plusieurs lignes. Un autre usage est la création de fichiers à partir d’un script. Dans l’exemple suivant, on envoie un émail sur plusieurs lignes avec la commande mail
.
mail mon@adresse <<FIN
ceci
est
un
test
FIN
Exercice : Créer des fichiers avec un script bash.
Par exemple un script qui crée un fichier personnalisé :
#!/bin/bash
n=1
touch fichier-$n.txt
cat << EOF > fichier-$n.txt
Ceci est le fichier n°$n
Ligne 2
Ligne 3
Ligne 4
EOF
echo "fichier-$n créé"
1.4. Redirection de la sortie standard
Les données vont de gauche à droite.
programme > fichier
Par exemple, avec les droits de root :
fdisk -l /dev/?da > partitions.txt
Ceci lance fdisk
et redirige la sortie vers le fichier partitions.txt. La sortie n’est pas visible a l’écran. Notez que le shell lit cette commande à partir de la droite : le fichier partitions.txt est d’abord créé s’il n’existait pas auparavant, écrasé dans le cas contraire car l’opérateur “>
” est utilisé.
L’opérateur “>>
” ajoute la sortie standard à un fichier sans l’écraser.
Redirection de la sortie standard :
---- > ----
PROCESSUS ---- >> ---- FICHIER / PÉRIPHÉRIQUE
---- 1> ----
1.5. Exemples de redirection de la sortie standard
-
>
crée un nouveau fichier avec la sortie standard -
>>
ajoute la sortie au fichier
Par exemple :
date > date.txt
cat date.txt
dim fév 21 04:52:01 CET 2016
date >> date.txt
cat date.txt
dim fév 21 04:52:01 CET 2016
dim fév 21 04:53:09 CET 2016
date > date.txt
cat date.txt
dim fév 21 04:53:32 CET 2016
1.6. Redirection de la sortie erreur standard
programme 2> fichier_erreur
stdin
, stdout
et stderr
sont représentés respectivement par 0, 1 et 2. Cela nous permet de choisir le flux d’erreur standard. Par exemple, vers une corbeille :
ls /fake / 2> /dev/null
Par exemple, vers un fichier :
ls /fake 2> err.txt
Redirection de l’erreur standard :
PROCESSUS ---- 2> ---- FICHIER / PÉRIPHÉRIQUE
1.7. Travailler avec les redirections
La commande suivante donne des erreurs et une sortie standard :
find /etc/ -name "*.crt"
/etc/ssl/certs/ca-certificates.crt
find: /etc/ssl/private: Permission denied
...
Isoler la sortie erreur :
find /etc/ -name "*.crt" > /dev/null
find: /etc/ssl/private: Permission denied
Isoler la sortie standard :
find /etc/ -name "*.crt" 2> /dev/null
/etc/ssl/certs/ca-certificates.crt
Diviser les sorties :
find /etc/ -name "*.crt" 2> /dev/null
/etc/ssl/certs/ca-certificates.crt
find /etc/ -name "*.crt" > crt.txt 2> crt.err
cat crt.txt
/etc/ssl/certs/ca-certificates.crt
cat crt.err
find: /etc/ssl/private: Permission denied
Rediriger une sortie vers l’autre, ici la sortie d’erreur sur la sortie standard :
find /etc/ -name "*.crt" 2>&1
Le symbôle &1
identifie la sortie standard demanière certaine. Sans le &
la sortie d’erreur sera redirigée dans un fichier nommé 1
.
Exemple final récapitulatif à méditer :
Avec le fichier fdisk.txt
.
fdisk /dev/?da < fdisk.txt 2> /dev/null > resultat.txt
Le fichier fdisk.txt
envoie des commandes en entrée à l’exécutable fdisk
, le résultat sans les erreurs est écrit dans le fichier resultat.txt
.
1.8. Tubes
programme1 | programme2
Les tubes (“pipe” en anglais) sont représentés par l’opérateur “|
”. Les données vont de gauche à droite. La figure suivante indique comment la sortie standard du premier processus est redirigée vers l’entrée standard du second processus.
Redirection à partir d’un tube :
PROCESSUS1 (stdout) ---- | ---- (stdin) PROCESSUS2
Exemple : la sortie standard de la première commande devient l’entrée de la seconde commande.
ps aux | grep login
Note : L’utilitaire pgrep
fournit le même résultat.
2. Outils de traitement du texte
2.1. cat
: éditeur rudimentaire
La commande cat
peut être utilisée comme un éditeur de texte rudimentaire.
cat > texte.txt
ligne 1
ligne 2
ligne 3
[Crtl+D]
Vous noterez l’utilisation de Ctrl+D
. Cette commande est utilisée pour clore la saisie.
2.2. cat
lecteur de texte
On utilise plus couramment cat
pour envoyer du texte vers la sortie standard.
Les options les plus courantes sont :
-
-n
numéroter chaque ligne de la sortie -
-b
numéroter uniquement les lignes non vides -
-A
afficher le retour charriot
Exemples :
cat texte.txt
ligne 1
ligne 2
ligne 3
cat -n /etc/resolv.conf
En fait, la commande cat
concatène en sortie standard plusieurs fichiers mis en arguments de la commande.
2.3. tac
lecteur inverse
tac
fait la même chose que cat
à l’exception qu’elle lit de la dernière ligne à la première.
tac texte.txt
ligne 3
ligne 2
ligne 1
2.4. head
et tail
On utilise souvent les commandes head
et tail
pour analyser les fichiers de journaux. Par défaut, ces commandes affichent 10 lignes. En voici les utilisations les plus courantes :
Afficher les 20 premières lignes de /var/log/messages
:
head -n 20 /var/log/messages
head -20 /var/log/messages
Afficher les 20 dernières lignes de /etc/aliases
:
tail -20 /etc/aliases
tail
a une option supplémentaire qui nous permet d’afficher la fin d’un texte en commençant par une ligne donnée.
Afficher le texte en partant de la ligne 25 de /var/log/messages
tail -n +25 /var/log/messages
tail
peut afficher un fichier en continu avec l’option -f
. C’est très pratique pour suivre les modifications d’un fichier en temps réel.
2.5. Commande tee
La commande tee permet à la fois de lire un flux et de le rediriger.
Par exemple, tee
donne la sortie et l’écrit dans le fichier ls1.txt :
ls | tee ls1.txt
La sortie de la liste de fichiers dont on compte les lignes est redirigée vers la sortie standard et dans le fichier count.txt
ls -l *.txt | wc -l | tee count.txt
3. Manipulation de texte
- Compter des lignes, des mots, des octets
- Remplacer des tabulations par des espaces
- Afficher les fichiers binaires
- Découper les fichiers
- Sélectionner les champs et les caractères avec cut
- Trouver des doublons
- Trier la sortie
- Couper des fichiers
- Jointure de texte
- Mise en forme de la sortie avec fmt et pr
- Convertir les caractères
3.1. Compter lignes, mots et octets avec la commande wc
La commande wc
compte le nombre d’octets, de mots et de lignes dans les fichiers.
Les options suivantes vous permettent de sélectionner ce qui nous intéresse :
-
-l
compte le nombre de lignes -
-w
compte le nombre de mots (words) -
-c
compte le nombre d’octets -
-m
compte le nombre de caractères - sans argument, wc compte ce qui est saisi dans stdin.
Par exemple :
wc -l /etc/passwd
cat /etc/passwd | wc -l
3.2. Remplacer les tabulations par des espaces
On utilise la commande expand
pour remplacer les tabulations par des espaces.
unexpand
est utilisé pour l’opération inverse.
3.3. Afficher les fichiers binaires
Il y a nombre d’outils pour cela. Les plus courants sont od
(octal dump) et hexdump
.
3.4. Découper les fichiers avec la commande split
La commande split
peut découper un fichier en plusieurs fichiers plus petits à partir de critères comme la taille ou le nombre de lignes. Par exemple, nous pouvons découper /etc/passwd
en fichiers de 5 lignes chacun :
split -l 5 /etc/passwd
Cette commande va créer des fichiers appelés xaa
, xab
, xac
, xad
, etc., chaque fichier contenant au plus 5 lignes. Tentez et vérifiez :
split -dl 5 /etc/passwd passwd
Il est possible de donner un préfixe plus significatif que “x
”, comme “pass-5
” :
split -l 5 /etc/passwd passwd-5
Cette commande crée des fichiers identiques à la commande précédente, mais ils sont désormais nommés passwd-5aa
, passwd-5ab
, passwd-5ac
, passwd-5ad
, …
3.5. Sélectionner les champs et les caractères avec cut
La commande cut
peut extraire une plage de caractères ou de champs de chaque ligne d’un texte.
- L’option
-c
est utilisée pour manipuler les caractères. - Syntaxe :
cut –c {plage1,plage2}
Exemple :
cut -c5-10,15- /etc/passwd
Cette commande extrait les caractères 5 à 10 puis 15 jusqu’à la fin pour chaque ligne de /etc/passwd
.
On peut spécifier le séparateur de champ (espace, virgule, etc.) d’un fichier ainsi que les champs à extraire. Ces options sont définies respectivement par les options -d
(delimiter) et -f
(field).
Syntaxe :
cut -d {séparateur} -f {champs}
Exemple :
cut -d: -f 1,7 --output-delimiter=" " /etc/passwd
Cette commande extrait les 1er et 7e champs de /etc/passwd
séparés par un espace. Le délimiteur de sortie est le même que le délimiteur d’entrée d’origine (par défaut, la tabulation). L’option --output-delimiter
vous permet de le changer.
3.6. Trouver des doublons avec la commande uniq
Éliminer les lignes successives en doublon : La commande uniq
n’envoie à STDOUT qu’une version des lignes successives identiques. Par exemple :
uniq > /tmp/list1
ligne 1
ligne 2
ligne 2
ligne 3
ligne 3
ligne 3
ligne 1
^D
cat /tmp/UNIQUE
sort | uniq > /tmp/UNIQUE
3.7. Trier la sortie avec la commande sort
Par défaut, sort
trie le texte par ordre alphabétique. Pour effectuer un tri numérique, utilisez l’option -n
.
cat << EOF > /tmp/list2
ligne 1
ligne 2
ligne 2
ligne 1
ligne 3
ligne 2
ligne 3
ligne 1
EOF
sort /tmp/list2
sort /tmp/list2 | uniq > /tmp/list3
3.8. Jointure de texte avec paste
La commande la plus facile est paste
qui “concatène” deux fichiers l’un à la suite de l’autre.
Syntaxe :
paste texte1 texte2
Exemples avec deux fichiers :
texte1 :
cat << EOF > texte1
01 Paris
02 Luxembourg
03 Berlin
04 Bruxelles
05 Londres
EOF
texte2 :
cat << EOF > texte2
01 France
02 Grand-Duché de Luxembourg
03 Allemagne
04 Belgique
05 Royaume-Uni
EOF
paste texte1 texte2
01 Paris 01 France
02 Luxembourg 02 Grand-Duché de Luxembourg
03 Berlin 03 Allemagne
04 Bruxelles 04 Belgique
05 Londres 05 Royaume-Uni
paste -s texte1 texte2
01 Paris 02 Luxembourg 03 Berlin 04 Bruxelles 05 Londres
01 France 02 Grand-Duché de Luxembourg 03 Allemagne 04 Belgique 05 Royaume-Uni
paste -s -d: texte1 texte2
01 Paris:02 Luxembourg:03 Berlin:04 Bruxelles:05 Londres
01 France:02 Grand-Duché de Luxembourg:03 Allemagne:04 Belgique:05 Royaume-Uni
paste -d: texte1 texte2
01 Paris:01 France
02 Luxembourg:02 Grand-Duché de Luxembourg
03 Berlin:03 Allemagne
04 Bruxelles:04 Belgique
05 Londres:05 Royaume-Uni
3.9. Jointure de texte avec join
Avec join
vous pouvez en plus préciser quels champs vous souhaitez à condition que les fichiers disposent d’un début de ligne commun.
Syntaxe :
join -j1 {champ_no} -j2{champ_no} texte1 texte2
ou
join -1 {champ_no} -2{champ_no} texte1 texte2
Le texte n’est envoyé à la sortie que si les champs sélectionnés correspondent.
Les comparaisons se font ligne par ligne et le processus s’arrête dès qu’il n’y a pas de correspondance, même s’il y a d’autres correspondances à la fin du fichier.
Par exemple avec les fichiers précédents :
join texte1 texte2
01 Paris France
02 Luxembourg Grand-Duché de Luxembourg
03 Berlin Allemagne
04 Bruxelles Belgique
05 Londres Royaume-Uni
Exercice optionnel : Regroupez les fichiers séparés précédemment.
3.10. Mise en forme de la sortie avec fmt
et pr
Vous pouvez modifier le nombre de caractères par ligne avec fmt
. Par défaut fmt
joint les lignes et génère des lignes de 75 caractères.
Options de fmt
:
-
-w
(width) nombre de caractères par ligne -
-s
découpe les lignes longues mais sans les remplir -
-u
sépare chaque mot par une espace et chaque phrase par deux espaces - On peut paginer les longs fichiers pour qu’ils correspondent à une taille donnée avec la commande
pr
. On peut contrôler la longueur des pages (66 lignes par défaut), la largeur (par défaut 72 caractères) ainsi que le nombre de colonnes. - Lorsqu’on produit un texte sur plusieurs colonnes, chaque colonne est tronquée uniformément en fonction de la largeur de page spécifiée. Cela veut dire que des caractères sont supprimés à moins d’avoir édité le texte de façon à éviter cela.
Par exemple :
curl -s https://lipsum.com/feed/json -o lipsum.txt
fmt < lipsum.txt
3.11. Convertir les caractères avec la commande tr
La commande tr
convertit un ensemble de caractères en un autre.
Convertir les majuscules en minuscules :
tr 'A-B' 'a-b' < fichier.txt
Changer de délimiteur dans /etc/passwd
tr ':' ' ' < /etc/passwd
join texte1 texte2 | tr ' ' ':'
01:Paris:France
02:Luxembourg:Grand-Duché:de:Luxembourg
03:Berlin:Allemagne
04:Bruxelles:Belgique
05:Londres:Royaume-Uni
Remarque : tr
a seulement deux arguments ! Le fichier n’est pas un argument.
3.12. Différentiel avec la commande diff
diff fichier1 fichier2