La commande Linux cut vous permet d’extraire des portions de texte de fichiers ou de flux de données. Elle est particulièrement utile pour travailler avec des données délimitées, comme les fichiers CSV. Voici ce que vous devez savoir.

La commande cut

La commande cut est un vétéran du monde Unix, qui a fait ses débuts en 1982 dans le cadre de l’UNIX AT&T System III. Son but dans la vie est de couper des sections de texte dans des fichiers ou des flux, selon les critères que vous avez définis. Sa syntaxe est aussi simple que son objectif, mais c’est cette simplicité commune qui le rend si utile.

Quelle est la différence entre Linux et BSD ?

Selon la tradition UNIX, en combinant cut avec d’autres utilitaires tels que grep, vous pouvez créer des solutions élégantes et puissantes à des problèmes difficiles. Bien qu’il existe différentes versions de cut, nous allons parler de la version standard de GNU/Linux. Sachez que d’autres versions, notamment la version cut que l’on trouve dans les variantes BSD, n’incluent pas toutes les options décrites ici.

Vous pouvez vérifier quelle version est installée sur votre ordinateur en lançant cette commande :

cut –version

Si vous voyez « GNU coreutils » dans la sortie, vous êtes sur la version que nous allons décrire dans cet article. Toutes les versions de cut possèdent certaines de ces fonctionnalités, mais la version Linux a été améliorée.

Premiers pas avec cut

Que nous introduisions des informations dans cut ou que nous utilisions cut pour lire un fichier, les commandes que nous utilisons sont les mêmes. Tout ce que vous pouvez faire sur un flux d’entrée avec cut peut être fait sur une ligne de texte d’un fichier, et vice versa. Nous pouvons demander à cut de travailler avec des octets, des caractères ou des champs délimités.

Pour sélectionner un seul octet, nous utilisons l’option -b (byte) et indiquons à cut quel(s) octet(s) nous voulons. Dans ce cas, il s’agit de l’octet 5. Nous envoyons la chaîne « how-to geek » dans la commande cut avec un pipe, « | », de echo .

echo ‘how-to geek’ | cut -b 5

Extraction d’un seul octet avec cut

Le cinquième octet de cette chaîne est « t », donc cut répond en imprimant « t » dans la fenêtre du terminal.

Pour spécifier une plage, nous utilisons un trait d’union. Pour extraire les octets 5 à – et y compris – 11, il faut lancer cette commande :

echo ‘how-to geek’ | cut -b 5-11

Extraction d’une plage d’octets avec cut

Vous pouvez fournir plusieurs octets ou plages d’octets en les séparant par des virgules. Pour extraire l’octet 5 et l’octet 11, utilisez cette commande :

echo ‘how-to geek’ | cut -b 5,11

Extraction de deux octets avec cut

Pour obtenir la première lettre de chaque mot, nous pouvons utiliser cette commande :

echo ‘how-to geek’ | cut -b 1,5,8

Extraction de trois octets avec cut

Si vous utilisez le trait d’union sans le premier chiffre, cut renvoie tout à partir de la position 1 jusqu’au chiffre. Si vous utilisez le trait d’union sans le deuxième chiffre, cut renvoie tout ce qui se trouve entre le premier chiffre et la fin du flux ou de la ligne.

echo ‘how-to geek’ | cut -b -6

echo ‘how-to geek’ | cut -b 8-

Extraction de plages d’octets avec cut

Utilisation de cut avec des caractères

L’utilisation de cut avec des caractères est à peu près la même que pour des octets. Dans les deux cas, une attention particulière doit être portée aux caractères complexes. En utilisant l’option -c (caractère), nous demandons à cut de travailler en termes de caractères et non d’octets.

echo ‘how-to geek’ | cut -c 1,5,8

echo ‘how-to geek’ | cut -c 8-11

Extraction de caractères et de plages de caractères avec cut

Tout cela fonctionne exactement comme prévu. Mais regardez cet exemple. C’est un mot de six lettres, donc demander à cut de retourner les caractères de un à six devrait retourner le mot entier. Mais ce n’est pas le cas. Il manque un caractère. Pour voir le mot entier, nous devons demander les caractères de un à sept.

echo ‘piñata’ | cut -c 1-6

echo ‘piñata’ | cut -c 1-7

Les caractères spéciaux peuvent occuper plus d’un caractère

Le problème est que le caractère « ñ » est en fait composé de deux octets. Nous pouvons le constater assez facilement. Nous avons un petit fichier texte contenant cette ligne de texte :

cat unicode.txt

Le contenu du fichier texte court

Nous allons examiner ce fichier avec l’utilitaire hexdump. L’utilisation de l’option -C (canonical) nous donne un tableau de chiffres hexadécimaux avec l’équivalent ASCII à droite. Dans le tableau ASCII, le « ñ » n’apparaît pas, mais des points représentent deux caractères non imprimables. Ce sont les octets mis en évidence dans la table hexadécimale.

hexdump -C unicode.txt

Hexdump du fichier texte de test

Ces deux octets sont utilisés par le programme d’affichage – dans ce cas, le shell Bash – pour identifier le « ñ ». De nombreux caractères Unicode utilisent trois octets ou plus pour représenter un seul caractère.

Si nous demandons le caractère 3 ou le caractère 4, on nous montre le symbole d’un caractère non imprimable. Si nous demandons les octets 3 et 4, le shell les interprète comme « ñ ».

echo ‘piñata’ | cut -c 3

echo ‘piñata’ | cut -c 4

echo ‘piñata’ | cut -c 3-4

Utilisation de cut pour extraire les caractères qui composent un caractère spécial

Utilisation de cut avec des données délimitées

Nous pouvons demander à cut de séparer les lignes de texte en utilisant un délimiteur spécifié. Par défaut, cut utilise un caractère de tabulation, mais il est facile de lui demander d’utiliser ce que l’on veut. Les champs du fichier « /etc/passwd » sont séparés par des deux-points  » : », nous allons donc les utiliser comme délimiteur et extraire du texte.

Les portions de texte entre les délimiteurs sont appelées champs, et sont référencées comme des octets ou des caractères, mais elles sont précédées de l’option -f (champs). Vous pouvez laisser un espace entre le « f » et le chiffre, ou non.

La première commande utilise l’option -d (delimiter) pour dire à cut d’utiliser  » : » comme délimiteur. Elle va extraire le premier champ de chaque ligne du fichier « /etc/passwd ». La liste sera longue, c’est pourquoi nous utilisons head avec l’option -n (nombre) pour n’afficher que les cinq premières réponses. La deuxième commande fait la même chose mais utilise tail pour nous montrer les cinq dernières réponses.

cut -d’:’ -f1 /etc/passwd | head -n 5

cut -d’:’ -f2 /etc/passwd | tail -n 5

Extraction d’une série de champs du fichier /etc/passwd

Pour extraire une sélection de champs, indiquez-les dans une liste séparée par des virgules. Cette commande extrait les champs un à trois, cinq et six.

cut -d’:’ -f1-3,5,6 /etc/passwd | tail -n 5

Extraction d’une série de champs du fichier /etc/passwd

En incluant grep dans la commande, nous pouvons rechercher les lignes qui incluent « /bin/bash ». Cela signifie que nous pouvons lister uniquement les entrées qui ont Bash comme interpréteur de commandes par défaut. Il s’agit généralement des comptes utilisateurs « normaux ». Nous demanderons les champs de un à six car le septième champ est le champ du shell par défaut et nous savons déjà ce qu’il est – nous le recherchons.

grep « /bin/bash » /etc/passwd | cut -d’:’ -f1-6

Extraction des champs un à six du fichier /etc/passwd

Une autre façon d’inclure tous les champs sauf un est d’utiliser l’option –complement. Cela inverse la sélection des champs et affiche tout ce qui n’a pas été demandé. Répétons la dernière commande mais ne demandons que le champ sept. Puis nous exécuterons à nouveau cette commande avec l’option –complement.

grep « /bin/bash » /etc/passwd | cut -d’:’ -f7

grep « /bin/bash » /etc/passwd | cut -d’:’ -f7 –complement

Utilisation de l’option –complement pour inverser la sélection d’un champ

La première commande trouve une liste d’entrées, mais le champ sept ne nous donne rien pour les distinguer, donc nous ne savons pas à qui les entrées font référence. Dans la deuxième commande, en ajoutant l’option –complement, nous obtenons tout sauf le champ sept.

Piping cut Into cut

En restant sur le fichier « /etc/passwd », extrayons le champ cinq. C’est le nom réel de l’utilisateur qui possède le compte utilisateur.

grep « /bin/bash » /etc/passwd | cut -d’:’ -f5

Le cinquième champ du fichier /etc/passwd peut avoir des sous-champs séparés par des virgules

Le cinquième champ a des sous-champs séparés par des virgules. Ils sont rarement remplis et apparaissent donc comme une ligne de virgules.

Nous pouvons supprimer les virgules en transférant la sortie de la commande précédente dans une autre invocation de cut . La deuxième instance de cut utilise la virgule « , » comme délimiteur. L’option -s (seulement délimité) indique à cut de supprimer les résultats qui ne contiennent pas du tout le délimiteur.

grep « /bin/bash » /etc/passwd | cut -d’:’ -s -f5 | cut -d’,’ -s -f1

Piping cut dans cut pour traiter deux types de délimiteurs

Comme l’entrée racine n’a pas de sous-champs à virgule dans le cinquième champ, elle est supprimée, et nous obtenons les résultats que nous recherchons – une liste des noms des « vrais » utilisateurs configurés sur cet ordinateur.

Le délimiteur de sortie

Nous disposons d’un petit fichier contenant quelques valeurs séparées par des virgules. Les champs de ces données fictives sont les suivants :

ID : Un numéro d'identification de la base de données
First (Prénom) : Le premier nom du sujet.
Last : Le nom de famille du sujet.
email : Leur adresse électronique.
Adresse IP : Leur adresse IP.
Marque : La marque du véhicule à moteur qu'ils conduisent.
Modèle : Le modèle de véhicule à moteur qu'ils conduisent.
Année : L'année de construction de leur véhicule à moteur.

cat petit.csv

Un fichier texte de données CSV fictives.

Si nous disons à cut d’utiliser la virgule comme délimiteur, nous pouvons extraire des champs comme nous l’avons fait auparavant. Parfois, vous aurez besoin d’extraire des données d’un fichier, mais vous ne voulez pas que le délimiteur de champ soit inclus dans les résultats. En utilisant l’option –output-delimiter, nous pouvons indiquer à cut quel caractère – ou en fait, quelle séquence de caractères – utiliser à la place du délimiteur réel.

cut -d ‘,’ -f 2,3 small.csv

cut -d ‘,’ -f 2,3 small.csv –output-delimiter=’ ‘

Utilisation de –output-delimiter pour changer le délimiteur dans les résultats

La deuxième commande indique à cut de remplacer les virgules par des espaces.

Nous pouvons aller plus loin et utiliser cette fonctionnalité pour convertir la sortie en une liste verticale. Cette commande utilise un caractère de nouvelle ligne comme délimiteur de sortie. Notez le « $ » que nous devons inclure pour que le caractère de nouvelle ligne soit pris en compte et non interprété comme une séquence littérale de deux caractères.

Nous utiliserons grep pour filtrer l’entrée de Morgane Renwick, et demanderons à cut d’imprimer tous les champs, du champ deux à la fin de l’enregistrement, et d’utiliser un caractère de nouvelle ligne comme délimiteur de sortie.

grep ‘renwick’ small.csv | cut -d ‘,’ -f2- –output-delimiter=$ »

Conversion d’un enregistrement en liste en utilisant un caractère de nouvelle ligne comme délimiteur de sortie.

Un vieil ami de l’or

À l’heure où nous écrivons ces lignes, la petite commande cut approche de son 40e anniversaire, et nous l’utilisons et écrivons encore à son sujet aujourd’hui. Je suppose que le découpage de texte est aujourd’hui le même qu’il y a 40 ans. C’est-à-dire beaucoup plus facile quand on a le bon outil en main.