Séance 3 : Flux de données¶
Flux standards¶
Que fait le programme suivant ?
#include <readline/readline.h>
int main(int argc, char* argv[]) {
char* nom = readline("Quel est votre nom ? ");
printf("Bonjour %s !\n", nom);
}
Note
Réponse typique : il lit une chaîne depuis le clavier, puis affiche une chaîne à l'écran. Mais c'est en fait un cas pariculier de ce qu'il fait.
Sous Linux, la plupart des programmes démarrent avec 3 flux de données préalablement ouverts :
l'entrée standard, destinée à alimenter le programme en données,
la sortie standard, destinée à recevoir les résultats du programme,
l'erreur standard, destinée à recevoir les messages d'erreur générés par le programme.
Note
On emploie parfois le mot « fichier » plutôt que flux, bien qu'il prête à confusion.
Les processus lancés par le shell héritent de ses flux standard, et donc correspondent par défaut au clavier et a l'affichage du terminal.
Mais il est possible de changer cela.
Redirection¶
Une ligne de commande peut comporter un ou plusieurs des éléments suivants :
<
suivi d'un nom de fichier (chemin)>
suivi d'un nom de fichier (chemin)2>
suivi d'un nom de fichier (chemin)
Ces éléments redirigent (ou « rebranchent ») l'un des flux standards (l'entrée, la sortie et l'erreur standard, respectivement) sur le fichier indiqué.
Indication
Les redirections sont interprétéss par les shell avant d'exécuter le programme, et ne sont donc pas vues par le programme.
Exemple :
ls -l >mes_fichiers.txt
/dev/null¶
/dev/null
est un fichier virtuel présent sur tous les systèmes UNIX.
Il agit comme un « trou noir », tout ce qui est écrit dans ce fichiers est simplement supprimé.
Exemple :
# n'affiche que les messages d'erreurs
# (répertoires non autorisés pour l'utilisateur)
ls /var/*/* >/dev/null
Redirection par ajout¶
Les redirections classiques >
et 2>
vident le fichier destination avant d'écrire dedans.
Si on souhaite conserver le contenu précédent du fichier,
on peut utiliser à la place >>
ou 2>>
, respectivement.
Exemple :
ls -l Documents >>mes_fichiers.txt
Outils de manipulation de texte¶
Philosophie UNIX¶
chaque outil fait une seule chose, mais la fait bien
le SE offre des mécanismes pour combiner les outils
wc [options] — word count¶
Compte les mots (ou d'autres choses) sur son entrée standard.
En l'absence d'options, affiche le nombre de lignes, de mots et d'octets.
-
-c
,
--bytes
¶
Affiche le nombre d'octets.
-
-w
,
--words
¶
Affiche le nombre de mots.
-
-l
,
--lines
¶
Affiche le nombre de lignes.
-
-L
,
--max-line-length
¶
Affiche la longueur de la ligne la plus longue.
sort [OPTIONS]¶
Trie les lignes lues sur l'entrée standard, et les affiche dans l'ordre sur la sortie standard.
-
-r
,
--reverse
¶
Inverse l'ordre du tri.
-
-n
,
--numeric-sort
¶
Interprète les valeurs comme des nombres si possible.
Note
Dans l'ordre alphabétique (utilisé par défaut),
10
arrive avant2
par exemple.
-
-k
,
--key
=NUMÉRO
¶ Le champs sur lequel trier (les champs sont délimitées par tous les types d'espaces).
Note
En fait l'option
-k
est beaucoup plus flexible que cela.
-
-t
,
--field-separator
=CARACTÈRE
¶ Utilise
CARACTÈRE
comme délimiteur de champs pour-k
, au lieu des espaces.
cut [OPTIONS]¶
Reproduit sur sa sortie standard une sous-partie de chaque ligne lue sur son entrée standard.
-
-f
,
--fields
=LIST
¶ Ne conserve que les champs spécifiés par
LIST
, qui est une liste séparée par des virgules de numéros (le premier champs est a le numéro 1) ou de plages de numéros.Les champs sont délimités par des tabulations.
-
-d
,
--delimiter
=CARACTÈRE
¶ Utilise
CARACTÈRE
comme délimiteur de champs pour-f
, au lieu des tabulation.
-
-c
,
--characters
=LIST
¶ Ne conserve que les caractères spécifiés par
LIST
, avec la même syntaxe que pour-f
.
Exemples d'utilisation de cut¶
# ne garde que les colonnes 1 et 3
cut -d, -f1,3 <data.csv >columns.csv
# affiche les noms d'utilisateurs inscrits
cut -d: -f1 </etc/passwd
# tronque à 10 caractères chaque ligne de src
cut -c1-10 <src >dest
egrep [OPTIONS] <regex>¶
N'affiche sur la sortie standard que les lignes (lues sur l'entrée standard)
contenant l'expression régulière <regex>
.
-
-i
,
--ignore-case
¶
Ignore les différences de casse (différence majuscule/minuscule) entre le texte lu et l'expression régulière.
-
-v
,
--invert-match
¶
Au lieu d'afficher les lignes qui contiennent
<regex>
, affiche celles qui ne la contiennent pas.
tr <set1> <set2> | tr -d <set1> — translate¶
Reproduit sur sa sortie standard le texte lu sur l'entrée standard, en modifiant (première variante) ou supprimant (deuxième variante) certains caractères.
-
<set1>
Une liste de caractères, énumérés en extension, ou sous forme de plages de caractères séparés par un tiret
-
.Exemple :
02468
,a-zàâéèêîôû
,a-zA-Z
-
-c
,
--complement
¶
Transforme les caractères qui n'appartiennent pas à
<set1>
.
-
<set2>
Une liste de caractères, suivant les mêmes règles que
<set1>
.Chaque caractère de
<set1>
sera remplacé par le caractère correspondant de<set2>
. Si<set2>
est plus court que<set1>
, le dernier caractère est implicitement répété autant de fois que nécessaire.
-
-d
,
--delete
¶
Supprime les éléments de
<set1>
.
Exemples d'utilisation de tr¶
# remplace toutes les majuscules par des minuscules
tr A-Z a-z <src >dest
# remplace tous les chiffres par X
tr 0-9 X <src >dest
# remplace tout ce qui n'est pas une lettre par une espace
tr -c A-Za-z " " <src >dest
# supprime les espaces, tabulations, retours à la ligne
tr -d " \t\n" <src >dest
sed -r s/<regex>/<subst>∕g¶
Reproduit sur sa sortie standard le texte lu sur l'entrée standard,
en remplaçant toutes les occurences de l'expression régulière
par le texte <subst>
(qui peut être vide).
Note
sed
(serial editor) est en fait un éditeur de texte programmable.
Ceci n'est qu'une des nombreuses instructions qu'il supporte.
Expressions régulières¶
Une expression régulière (ou regex) décrit dans une syntaxe spécialisée une famille de chaînes de caractères.
Par exemple :
a.*z
: tout chaîne qui commence para
et se termine parz
[a-z]{1,5}
: tous les mots de 1 à 5 lettres minuscules\d{2}/\d{2}/\d{4}
: toutes les dates au format jj/mm/aaaa (un peu plus)[a-z0-9.-]+@[a-z0-9.-]+(\.[a-z]+)*
: toutes les adresses e-mail (un peu moins)
Les expressions régulières sont également utilisables
dans la plupart les langages de programmation,
dans les fonctions de recherche avancée des éditeurs de texte,
...
Caractères spéciaux¶
.
: n'importe quel caractère[...]
: un caractère appartenant à la séquence décrite, exemples :[xyz]
: un des caractèresx
,y
ouz
[^xyz]
: n'importe quel caractère autre quex
,y
ouz
[0-9]
: n'importe quel chiffre décimal[a-zA-Z_]
: n'importe quelle lettre minuscule ou majuscule, ou l'underscore.
^
: le début de la ligne$
: la fin de la ligne
Modificateurs¶
Si on suppose que a et b sont des expressions régulières quelconques :
(a)*
: un texte qui satisfait a zéro fois ou plus(a)+
: un texte qui satisfait a une fois ou plus(a)?
: un texte qui satisfait a zéro ou une fois(a){i,j}
: un texte qui satisfait a entre i et j fois(a)|(b)
: un texte qui satisfait a ou b
Échappements¶
Pour éviter que egrep
ou sed
n'interprète un caractère spécial
on le fera précéder d'un antislash (\
).
Exemple:
# affiche toutes les lignes de src qui contiennent un a suivi d'une étoile
egrep "a\*" <src
Avertissement
Les expressions régulière sont très similaires aux méta-caractères du shell, à la fois dans leur objectif et dans leur syntaxe. Mais attention, il y a des différences de syntaxe (par exemple
*
).À cause de cette similitude syntaxique, il est recommandé de toujours mettre les expressions régulières entre guillemets, pour éviter que le shell n'interprète les méta-caractères qu'elles contiennent...
En particulier, les anti-slash d'échappement destinés à
egrep
oused
doivent eux-même être échappés pour ne pas être interprétés par le shell !
En savoir plus¶
Tubes¶
Un tube (en anglais pipe) est un canal de communication quasi-synchrone entre deux programmes.
L'un des programmes écrit des données à une « extrémité » du tube ; l'autres les récupère en lisant à l'autres « extrémité ».
Contrairement à un fichier, les données écrites dans le tube ne sont pas stockées.
Création d'un tube en ligne de commande¶
En concaténant deux lignes de commandes, séparées par le caractère |
,
on demande au shell
de créer un tube,
d'exécuter le programme de gauche, après avoir redirigé sa sortie standard sur une extrémité, et
d'exécuter en parallèle le programme de droite, après avoir redirigé son entrée standard sur l'autre extrémité.
Le shell attend ensuite la fin des deux programmes.
# affiche les fichiers dont le nom est composé
# uniquement de minuscules ou uniquement de majuscules
ls | egrep "([a-z]+)|([A-Z]+)"
Une telle ligne de commande est appelée un pipeline.
Il est possible de concaténer plus de deux commandes ainsi.
# affiche les fichiers dont le nom a le format IMG_<numéro>.png
# triés par numéro
ls | egrep "IMG_[0-9]+.png" | sort -n -k2 -t_
Travaux dirigés¶
Exercice 1 : redirections¶
Stockez, dans un fichier texte, la liste des fichiers et répertoires de votre répertoire d’accueil. Vérifiez que cela a fonctionné.
Écrivez "fin" à la fin de ce fichier sans utiliser d'éditeur de texte.
Enregistrez dans un fichier la page de manuel (
man
) de la commandels
.
Exercice 2 : filtres et expressions régulières (encore)¶
Récupérez le fichier fruits.txt.
Affichez :
Les lignes dont le nom est "Fraise" ou "fraise"
Les lignes ou "ai" est présent dans le nom
Les lignes dont le nom se finit en "se"
Les lignes dont le nom contient un chiffre
Les lignes dont le nom fait exactement 5 caractères
Exercice 3 : filtres et expressions régulières¶
Récupérez le fichier contacts.txt.
Chaque ligne de ce fichier comporte un nom, une ville et un numéro de téléphones,
séparés par le caractère deux-points (:
).
Affichez uniquement les noms et numéros de téléphone de l’annuaire.
Affichez les informations sur un correspondant connu par son nom.
Affichez l’annuaire trié sur le nom.
Constituez un nouvel annuaire contenant tous les correspondants sauf "Jean Dupont".
Affichez le nombre de correspondants.
Affichez les correspondants qui habitent Lyon.
Affichez les correspondants dont le nom commence par "d".
Exercice 4: Dé-htmliseur¶
Enregistrez cette page Web dans votre répertoire home.
À l'aide d'une ligne de commande, créez un fichier qui contient le texte de ce ce fichier HTML, débarassé de toutes ses balises.