La commande cut est l'outil canonique pour supprimer les "colonnes" d'un fichier texte. Dans ce contexte, une "colonne" peut être définie comme une plage de caractères ou d'octets identifiés par leur position physique sur la ligne, ou une plage de champs délimités par un séparateur.
J'ai déjà écrit sur l'utilisation des commandes AWK. Dans ce guide détaillé, je vais vous expliquer quatre exemples essentiels et pratiques de la commande cut sous Linux qui vous aideront énormément.
4 exemples pratiques de la commande Cut sous Linux
Si vous préférez, vous pouvez regarder cette vidéo expliquant les mêmes exemples pratiques de commande de coupe que j'ai énumérés dans l'article.
1. Travailler avec des plages de caractères
Lorsqu'il est invoqué avec le -c
option de ligne de commande, la commande de coupe supprimera le caractère plages.
Comme tout autre filtre, la commande cut ne modifie pas le fichier d'entrée en place mais copie les données modifiées sur sa sortie standard. Il est de votre responsabilité de rediriger la sortie de la commande vers un fichier pour enregistrer le résultat ou d'utiliser un tube pour l'envoyer en entrée à une autre commande.
Si vous avez téléchargé les exemples de fichiers de test utilisés dans la vidéo ci-dessus, vous pouvez voir le BALANCE.txt
fichier de données, tout droit sorti d'un logiciel de comptabilité que ma femme utilise dans son travail :
sh$ head BALANCE.txt
ACCDOC ACCDOCDATE ACCOUNTNUM ACCOUNTLIB ACCDOCLIB DEBIT CREDIT
4 1012017 623477 TIDE SCHEDULE ALNEENRE-4701-LOC 00000001615,00
4 1012017 445452 VAT BS/ENC ALNEENRE-4701-LOC 00000000323,00
4 1012017 4356 PAYABLES ALNEENRE-4701-LOC 00000001938,00
5 1012017 623372 ACCOMODATION GUIDE ALNEENRE-4771-LOC 00000001333,00
5 1012017 445452 VAT BS/ENC ALNEENRE-4771-LOC 00000000266,60
5 1012017 4356 PAYABLES ALNEENRE-4771-LOC 00000001599,60
6 1012017 4356 PAYABLES FACT FA00006253 - BIT QUIROBEN 00000001837,20
6 1012017 445452 VAT BS/ENC FACT FA00006253 - BIT QUIROBEN 00000000306,20
6 1012017 623795 TOURIST GUIDE BOOK FACT FA00006253 - BIT QUIROBEN 00000001531,00
Il s'agit d'un fichier texte à largeur fixe puisque les champs de données sont remplis avec un nombre variable d'espaces pour s'assurer qu'ils s'affichent sous la forme d'un tableau bien aligné.
En corollaire, une colonne de données commence et se termine toujours à la même position de caractère sur chaque ligne. Il y a cependant un petit écueil :malgré son nom, la cut
la commande nécessite en fait que vous spécifiiez la plage de données que vous souhaitez conserver , et non la plage que vous souhaitez supprimer . Donc, si j'ai besoin de seulement le ACCOUNTNUM
et ACCOUNTLIB
colonnes dans le fichier de données ci-dessus, j'écrirais que :
sh$ cut -c 25-59 BALANCE.txt | head
ACCOUNTNUM ACCOUNTLIB
623477 TIDE SCHEDULE
445452 VAT BS/ENC
4356 /accountPAYABLES
623372 ACCOMODATION GUIDE
445452 VAT BS/ENC
4356 PAYABLES
4356 PAYABLES
445452 VAT BS/ENC
623795 TOURIST GUIDE BOOK
Qu'est-ce qu'une plage ?
Comme nous venons de le voir, la commande cut nécessite de spécifier la plage de données que nous souhaitons conserver. Alors, introduisons plus formellement ce qu'est une plage :pour le cut
, une plage est définie par une position de début et de fin séparées par un trait d'union. Les plages sont basées sur 1, c'est-à-dire que le premier élément de la ligne est le numéro d'élément 1, et non 0. Les plages sont inclusives :le début et la fin seront conservés dans la sortie, ainsi que tous les caractères entre eux. C'est une erreur de spécifier une plage dont la position de fin est avant ("inférieure") que sa position de départ. Comme raccourci, vous pouvez omettre le début ou valeur finale comme décrit dans le tableau ci-dessous :
a-b
:la plage entre a et b (inclus)a
:équivalent à la plagea-a
-b
:équivalent à1-a
b-
:équivalent àb-∞
Les commandes de coupe permettent de spécifier plusieurs plages en les séparant par une virgule. Voici quelques exemples :
# Keep characters from 1 to 24 (inclusive)
cut -c -24 BALANCE.txt
# Keep characters from 1 to 24 and 36 to 59 (inclusive)
cut -c -24,36-59 BALANCE.txt
# Keep characters from 1 to 24, 36 to 59 and 93 to the end of the line (inclusive)
cut -c -24,36-59,93- BALANCE.txt
Une limitation (ou caractéristique, selon la façon dont vous le voyez) de la cut
commande est qu'elle ne ne réorganisera jamais les données . Ainsi, la commande suivante produira exactement le même résultat que la précédente, bien que les plages soient spécifiées dans un ordre différent :
cut -c 93-,-24,36-59 BALANCE.txt
Vous pouvez vérifier cela facilement en utilisant le diff
commande :
diff -s <(cut -c -24,36-59,93- BALANCE.txt) \
<(cut -c 93-,-24,36-59 BALANCE.txt)
Files /dev/fd/63 and /dev/fd/62 are identical
De même, la cut
la commande ne duplique jamais les données :
# One might expect that could be a way to repeat
# the first column three times, but no...
cut -c -10,-10,-10 BALANCE.txt | head -5
ACCDOC
4
4
4
5
Il convient de mentionner qu'il y avait une proposition pour un -o
possibilité de lever ces deux dernières limitations, permettant la cut
utilitaire pour réorganiser ou dupliquer des données. Mais cela a été rejeté par le comité POSIX"parce que ce type d'amélioration est en dehors du champ d'application du projet de norme IEEE P1003.2b."
Pour ma part, je ne connais aucune version coupée mettant en œuvre cette proposition en tant qu'extension. Mais si vous le faites, s'il vous plaît, partagez-le avec nous en utilisant la section des commentaires !
2. Travailler avec des plages d'octets
Lorsqu'il est invoqué avec le -b
option de ligne de commande, la commande cut supprimera byte plages.
À première vue, il n'y a pas de différence évidente entre caractère et octet plages :
sh$ diff -s <(cut -b -24,36-59,93- BALANCE.txt) \
<(cut -c -24,36-59,93- BALANCE.txt)
Files /dev/fd/63 and /dev/fd/62 are identical
C'est parce que mon exemple de fichier de données utilise le codage de caractères US-ASCII ("jeu de caractères") comme file -i
commande peut le deviner correctement :
sh$ file -i BALANCE.txt
BALANCE.txt: text/plain; charset=us-ascii
Dans ce codage de caractères, il existe un mappage un à un entre les caractères et les octets. En utilisant un seul octet, vous pouvez théoriquement encoder jusqu'à 256 caractères différents (chiffres, lettres, ponctuations, symboles, …) En pratique, ce nombre est beaucoup plus faible car les encodages de caractères prévoient certaines valeurs particulières (comme les 32 ou 65 caractères de contrôle trouve généralement). Quoi qu'il en soit, même si nous pouvions utiliser la gamme complète d'octets, ce serait loin d'être suffisant pour stocker la variété de l'écriture humaine. Ainsi, aujourd'hui, le mappage un à un entre les caractères et les octets est plus l'exception que la norme et est presque toujours remplacé par l'encodage multi-octets UTF-8 omniprésent. Voyons maintenant comment la commande cut pourrait gérer cela.
Travailler avec des caractères multioctets
Comme je l'ai dit précédemment, les exemples de fichiers de données utilisés comme exemples pour cet article proviennent d'un logiciel de comptabilité utilisé par ma femme. Il ajoute qu'elle a récemment mis à jour ce logiciel et, après cela, les fichiers texte exportés étaient légèrement différents. Je vous laisse essayer de voir la différence par vous-même :
sh$ head BALANCE-V2.txt
ACCDOC ACCDOCDATE ACCOUNTNUM ACCOUNTLIB ACCDOCLIB DEBIT CREDIT
4 1012017 623477 TIDE SCHEDULE ALNÉENRE-4701-LOC 00000001615,00
4 1012017 445452 VAT BS/ENC ALNÉENRE-4701-LOC 00000000323,00
4 1012017 4356 PAYABLES ALNÉENRE-4701-LOC 00000001938,00
5 1012017 623372 ACCOMODATION GUIDE ALNÉENRE-4771-LOC 00000001333,00
5 1012017 445452 VAT BS/ENC ALNÉENRE-4771-LOC 00000000266,60
5 1012017 4356 PAYABLES ALNÉENRE-4771-LOC 00000001599,60
6 1012017 4356 PAYABLES FACT FA00006253 - BIT QUIROBEN 00000001837,20
6 1012017 445452 VAT BS/ENC FACT FA00006253 - BIT QUIROBEN 00000000306,20
6 1012017 623795 TOURIST GUIDE BOOK FACT FA00006253 - BIT QUIROBEN 00000001531,00
Le titre de cette section peut vous aider à trouver ce qui a changé. Mais, trouvé ou non, voyons maintenant les conséquences de ce changement :
sh$ cut -c 93-,-24,36-59 BALANCE-V2.txt
ACCDOC ACCDOCDATE ACCOUNTLIB DEBIT CREDIT
4 1012017 TIDE SCHEDULE 00000001615,00
4 1012017 VAT BS/ENC 00000000323,00
4 1012017 PAYABLES 00000001938,00
5 1012017 ACCOMODATION GUIDE 00000001333,00
5 1012017 VAT BS/ENC 00000000266,60
5 1012017 PAYABLES 00000001599,60
6 1012017 PAYABLES 00000001837,20
6 1012017 VAT BS/ENC 00000000306,20
6 1012017 TOURIST GUIDE BOOK 00000001531,00
19 1012017 SEMINAR FEES 00000000080,00
19 1012017 PAYABLES 00000000080,00
28 1012017 MAINTENANCE 00000000746,58
28 1012017 VAT BS/ENC 00000000149,32
28 1012017 PAYABLES 00000000895,90
31 1012017 PAYABLES 00000000240,00
31 1012017 VAT BS/DEBIT 00000000040,00
31 1012017 ADVERTISEMENTS 00000000200,00
32 1012017 WATER 00000000202,20
32 1012017 VAT BS/DEBIT 00000000020,22
32 1012017 WATER 00000000170,24
32 1012017 VAT BS/DEBIT 00000000009,37
32 1012017 PAYABLES 00000000402,03
34 1012017 RENTAL COSTS 00000000018,00
34 1012017 PAYABLES 00000000018,00
35 1012017 MISCELLANEOUS CHARGES 00000000015,00
35 1012017 VAT BS/DEBIT 00000000003,00
35 1012017 PAYABLES 00000000018,00
36 1012017 LANDLINE TELEPHONE 00000000069,14
36 1012017 VAT BS/ENC 00000000013,83
J'ai copié ci-dessus la sortie de la commande in-extenso il devrait donc être évident que quelque chose s'est mal passé avec l'alignement des colonnes.
L'explication est que le fichier de données d'origine ne contenait que des caractères US-ASCII (symbole, ponctuations, chiffres et lettres latines sans signes diacritiques)
Mais si vous regardez attentivement le fichier produit après la mise à jour du logiciel, vous pouvez voir que le nouveau fichier de données d'exportation conserve désormais les lettres accentuées. Par exemple, la société nommée "ALNÉENRE" est désormais correctement orthographiée alors qu'elle était auparavant exportée sous le nom "ALNEENRE" (sans accent)
Le file -i
l'utilitaire n'a pas manqué ce changement puisqu'il signale maintenant que le fichier est encodé en UTF-8 :
sh$ file -i BALANCE-V2.txt
BALANCE-V2.txt: text/plain; charset=utf-8
Pour voir comment sont encodées les lettres accentuées dans un fichier UTF-8, on peut utiliser le hexdump
utilitaire qui nous permet de regarder directement les octets d'un fichier :
# To reduce clutter, let's focus only on the second line of the file
sh$ sed '2!d' BALANCE-V2.txt
4 1012017 623477 TIDE SCHEDULE ALNÉENRE-4701-LOC 00000001615,00
sh$ sed '2!d' BALANCE-V2.txt | hexdump -C
00000000 34 20 20 20 20 20 20 20 20 20 31 30 31 32 30 31 |4 101201|
00000010 37 20 20 20 20 20 20 20 36 32 33 34 37 37 20 20 |7 623477 |
00000020 20 20 20 54 49 44 45 20 53 43 48 45 44 55 4c 45 | TIDE SCHEDULE|
00000030 20 20 20 20 20 20 20 20 20 20 20 41 4c 4e c3 89 | ALN..|
00000040 45 4e 52 45 2d 34 37 30 31 2d 4c 4f 43 20 20 20 |ENRE-4701-LOC |
00000050 20 20 20 20 20 20 20 20 20 20 20 20 20 30 30 30 | 000|
00000060 30 30 30 30 31 36 31 35 2c 30 30 20 20 20 20 20 |00001615,00 |
00000070 20 20 20 20 20 20 20 20 20 20 20 0a | .|
0000007c
Sur la ligne 00000030 du hexdump
sortie, après un tas d'espaces (octet 20
), vous pouvez voir :
- la lettre
A
est encodé sous la forme de l'octet41
, - la lettre
L
est encodé sur l'octet4c
, - et la lettre
N
est encodé sous la forme de l'octet4e
.
Mais, la LETTRE MAJUSCULE LATINE E MAJUSCULE AIGU (comme c'est le nom officiel de la lettre É dans la norme Unicode) est encodé à l'aide des deux octets c3 89
Et voici le problème :utiliser le cut
La commande avec des plages exprimées en positions d'octet fonctionne bien pour les encodages de longueur fixe, mais pas pour ceux de longueur variable comme UTF-8 ou Shift JIS. Ceci est clairement expliqué dans l'extrait non normatif suivant du standard POSIX :
Les versions antérieures de l'utilitaire de coupe fonctionnaient dans un environnement où les octets et les caractères étaient considérés comme équivalents (traitement moduloet dans certaines implémentations). Dans le monde étendu des caractères multi-octets, la nouvelle option -b a été ajoutée.
Hé, attendez une minute ! Je n'utilisais pas le -b
option dans l'exemple "défectueux" ci-dessus, mais le -c
option. Donc, ne devrait pas qui ont fonctionné ?!?
Oui, il devrait :c'est dommage, mais nous sommes en 2018 et malgré cela, depuis GNU Coreutils 8.30, l'implémentation GNU de l'utilitaire de coupe ne gère toujours pas correctement les caractères multi-octets. Pour citer la documentation GNU, le -c
l'option est "Identique à -b pour l'instant, mais l'internationalisation va changer cela[… ]" — une mention présente depuis plus de 10 ans maintenant !
D'autre part, l'implémentation OpenBSD de l'utilitaire de coupe est conforme à POSIX et respectera les paramètres régionaux actuels pour gérer correctement les caractères multi-octets :
# Ensure subseauent commands will know we are using UTF-8 encoded
# text files
openbsd-6.3$ export LC_CTYPE=en_US.UTF-8
# With the `-c` option, cut works properly with multi-byte characters
openbsd-6.3$ cut -c -24,36-59,93- BALANCE-V2.txt
ACCDOC ACCDOCDATE ACCOUNTLIB DEBIT CREDIT
4 1012017 TIDE SCHEDULE 00000001615,00
4 1012017 VAT BS/ENC 00000000323,00
4 1012017 PAYABLES 00000001938,00
5 1012017 ACCOMODATION GUIDE 00000001333,00
5 1012017 VAT BS/ENC 00000000266,60
5 1012017 PAYABLES 00000001599,60
6 1012017 PAYABLES 00000001837,20
6 1012017 VAT BS/ENC 00000000306,20
6 1012017 TOURIST GUIDE BOOK 00000001531,00
19 1012017 SEMINAR FEES 00000000080,00
19 1012017 PAYABLES 00000000080,00
28 1012017 MAINTENANCE 00000000746,58
28 1012017 VAT BS/ENC 00000000149,32
28 1012017 PAYABLES 00000000895,90
31 1012017 PAYABLES 00000000240,00
31 1012017 VAT BS/DEBIT 00000000040,00
31 1012017 ADVERTISEMENTS 00000000200,00
32 1012017 WATER 00000000202,20
32 1012017 VAT BS/DEBIT 00000000020,22
32 1012017 WATER 00000000170,24
32 1012017 VAT BS/DEBIT 00000000009,37
32 1012017 PAYABLES 00000000402,03
34 1012017 RENTAL COSTS 00000000018,00
34 1012017 PAYABLES 00000000018,00
35 1012017 MISCELLANEOUS CHARGES 00000000015,00
35 1012017 VAT BS/DEBIT 00000000003,00
35 1012017 PAYABLES 00000000018,00
36 1012017 LANDLINE TELEPHONE 00000000069,14
36 1012017 VAT BS/ENC 00000000013,83
Comme prévu, lors de l'utilisation de -b
mode octet au lieu du -c
mode caractère, l'implémentation OpenBSD cut se comporte comme l'ancien cut
:
openbsd-6.3$ cut -b -24,36-59,93- BALANCE-V2.txt
ACCDOC ACCDOCDATE ACCOUNTLIB DEBIT CREDIT
4 1012017 TIDE SCHEDULE 00000001615,00
4 1012017 VAT BS/ENC 00000000323,00
4 1012017 PAYABLES 00000001938,00
5 1012017 ACCOMODATION GUIDE 00000001333,00
5 1012017 VAT BS/ENC 00000000266,60
5 1012017 PAYABLES 00000001599,60
6 1012017 PAYABLES 00000001837,20
6 1012017 VAT BS/ENC 00000000306,20
6 1012017 TOURIST GUIDE BOOK 00000001531,00
19 1012017 SEMINAR FEES 00000000080,00
19 1012017 PAYABLES 00000000080,00
28 1012017 MAINTENANCE 00000000746,58
28 1012017 VAT BS/ENC 00000000149,32
28 1012017 PAYABLES 00000000895,90
31 1012017 PAYABLES 00000000240,00
31 1012017 VAT BS/DEBIT 00000000040,00
31 1012017 ADVERTISEMENTS 00000000200,00
32 1012017 WATER 00000000202,20
32 1012017 VAT BS/DEBIT 00000000020,22
32 1012017 WATER 00000000170,24
32 1012017 VAT BS/DEBIT 00000000009,37
32 1012017 PAYABLES 00000000402,03
34 1012017 RENTAL COSTS 00000000018,00
34 1012017 PAYABLES 00000000018,00
35 1012017 MISCELLANEOUS CHARGES 00000000015,00
35 1012017 VAT BS/DEBIT 00000000003,00
35 1012017 PAYABLES 00000000018,00
36 1012017 LANDLINE TELEPHONE 00000000069,14
36 1012017 VAT BS/ENC 00000000013,83
3. Travailler avec des champs
Dans un certain sens, travailler avec des champs dans un fichier texte délimité est plus facile pour le cut
utilitaire, car il n'aura qu'à localiser les délimiteurs de champ (un octet) sur chaque ligne, en copiant ensuite textuellement le contenu du champ dans la sortie sans se soucier des problèmes d'encodage.
Voici un exemple de fichier texte délimité :
sh$ head BALANCE.csv
ACCDOC;ACCDOCDATE;ACCOUNTNUM;ACCOUNTLIB;ACCDOCLIB;DEBIT;CREDIT
4;1012017;623477;TIDE SCHEDULE;ALNEENRE-4701-LOC;00000001615,00;
4;1012017;445452;VAT BS/ENC;ALNEENRE-4701-LOC;00000000323,00;
4;1012017;4356;PAYABLES;ALNEENRE-4701-LOC;;00000001938,00
5;1012017;623372;ACCOMODATION GUIDE;ALNEENRE-4771-LOC;00000001333,00;
5;1012017;445452;VAT BS/ENC;ALNEENRE-4771-LOC;00000000266,60;
5;1012017;4356;PAYABLES;ALNEENRE-4771-LOC;;00000001599,60
6;1012017;4356;PAYABLES;FACT FA00006253 - BIT QUIROBEN;;00000001837,20
6;1012017;445452;VAT BS/ENC;FACT FA00006253 - BIT QUIROBEN;00000000306,20;
6;1012017;623795;TOURIST GUIDE BOOK;FACT FA00006253 - BIT QUIROBEN;00000001531,00;
Vous savez peut-être que le format de fichier est CSV (pour Comma-separated Value), même si le séparateur de champ n'est pas toujours une virgule. Par exemple, le point-virgule (;
) est fréquemment rencontré comme séparateur de champ, et c'est souvent le choix par défaut lors de l'exportation de données au format "CSV" dans les pays utilisant déjà la virgule comme séparateur décimal (comme nous le faisons en France - d'où le choix de ce caractère dans mon exemple de fichier ). Une autre variante populaire utilise un caractère de tabulation comme séparateur de champs, produisant ce que l'on appelle parfois un fichier de valeurs séparées par des tabulations. Enfin, dans le monde Unix et Linux, les deux-points (:
) est encore un autre séparateur de champ relativement courant que vous pouvez trouver, par exemple, dans le standard /etc/passwd
et /etc/group
fichiers.
Lorsque vous utilisez un format de fichier texte délimité, vous fournissez à la commande cut la plage de champs à conserver en utilisant le -f
option, et vous devez spécifier le délimiteur en utilisant le -d
option (sans le -d
option, l'utilitaire de coupe utilise par défaut un caractère de tabulation pour le séparateur) :
sh$ cut -f 5- -d';' BALANCE.csv | head
ACCDOCLIB;DEBIT;CREDIT
ALNEENRE-4701-LOC;00000001615,00;
ALNEENRE-4701-LOC;00000000323,00;
ALNEENRE-4701-LOC;;00000001938,00
ALNEENRE-4771-LOC;00000001333,00;
ALNEENRE-4771-LOC;00000000266,60;
ALNEENRE-4771-LOC;;00000001599,60
FACT FA00006253 - BIT QUIROBEN;;00000001837,20
FACT FA00006253 - BIT QUIROBEN;00000000306,20;
FACT FA00006253 - BIT QUIROBEN;00000001531,00;
Gestion des lignes ne contenant pas le délimiteur
Mais que se passe-t-il si une ligne du fichier d'entrée ne contient pas le délimiteur ? Il est tentant d'imaginer cela comme une ligne ne contenant que le premier champ. Mais ce n'est pas ce que fait l'utilitaire de coupe.
Par défaut, lors de l'utilisation de -f
, l'utilitaire de coupe affichera toujours textuellement une ligne qui ne contient pas le délimiteur (en supposant probablement qu'il s'agit d'une ligne non-données comme un en-tête ou un commentaire quelconque) :
sh$ (echo "# 2018-03 BALANCE"; cat BALANCE.csv) > BALANCE-WITH-HEADER.csv
sh$ cut -f 6,7 -d';' BALANCE-WITH-HEADER.csv | head -5
# 2018-03 BALANCE
DEBIT;CREDIT
00000001615,00;
00000000323,00;
;00000001938,00
Utilisation du -s
option, vous pouvez inverser ce comportement, donc cut
ignorera toujours cette ligne :
sh$ cut -s -f 6,7 -d';' BALANCE-WITH-HEADER.csv | head -5
DEBIT;CREDIT
00000001615,00;
00000000323,00;
;00000001938,00
00000001333,00;
Si vous êtes d'humeur hackeuse, vous pouvez exploiter cette fonctionnalité comme un moyen relativement obscur de ne conserver que les lignes contenant un caractère donné :
# Keep lines containing a `e`
sh$ printf "%s\n" {mighty,bold,great}-{condor,monkey,bear} | cut -s -f 1- -d'e'
Modifier le délimiteur de sortie
En tant qu'extension, l'implémentation GNU de cut permet d'utiliser un séparateur de champs différent pour la sortie en utilisant le --output-delimiter
choix :
sh$ cut -f 5,6- -d';' --output-delimiter="*" BALANCE.csv | head
ACCDOCLIB*DEBIT*CREDIT
ALNEENRE-4701-LOC*00000001615,00*
ALNEENRE-4701-LOC*00000000323,00*
ALNEENRE-4701-LOC**00000001938,00
ALNEENRE-4771-LOC*00000001333,00*
ALNEENRE-4771-LOC*00000000266,60*
ALNEENRE-4771-LOC**00000001599,60
FACT FA00006253 - BIT QUIROBEN**00000001837,20
FACT FA00006253 - BIT QUIROBEN*00000000306,20*
FACT FA00006253 - BIT QUIROBEN*00000001531,00*
Notez que dans ce cas, toutes les occurrences du séparateur de champs sont remplacées, et pas seulement celles à la limite des plages spécifiées sur les arguments de la ligne de commande.
4. Extensions GNU non POSIX
En parlant d'extension GNU non POSIX, quelques-unes d'entre elles peuvent être particulièrement utiles. Il convient de mentionner que les extensions suivantes fonctionnent aussi bien avec les plages d'octets, de caractères (pour ce que cela signifie dans l'implémentation GNU actuelle) ou de champs :--complement
Pensez à cette option comme au point d'exclamation dans une adresse sed (!
); au lieu de conserver les données correspondant à la plage donnée, cut
conservera les données NE correspondant PAS à la plage
# Keep only field 5
sh$ cut -f 5 -d';' BALANCE.csv |head -3
ACCDOCLIB
ALNEENRE-4701-LOC
ALNEENRE-4701-LOC
# Keep all but field 5
sh$ cut --complement -f 5 -d';' BALANCE.csv |head -3
ACCDOC;ACCDOCDATE;ACCOUNTNUM;ACCOUNTLIB;DEBIT;CREDIT
4;1012017;623477;TIDE SCHEDULE;00000001615,00;
4;1012017;445452;VAT BS/ENC;00000000323,00;
--zero-terminated
(-z
)
utilisez le caractère NUL comme fin de ligne au lieu du caractère de saut de ligne. Le -z
est particulièrement utile lorsque vos données peuvent contenir des caractères de nouvelle ligne intégrés, comme lorsque vous travaillez avec des noms de fichiers (puisque la nouvelle ligne est un caractère valide dans un nom de fichier, mais NUL ne l'est pas).
Pour vous montrer comment le -z
l'option fonctionne, faisons une petite expérience. Tout d'abord, nous allons créer un fichier dont le nom contient des retours à la ligne intégrés :
bash$ touch
Supposons maintenant que je souhaite afficher les 5 premiers caractères de chaque *.txt
nom de fichier. Une solution naïve échouera lamentablement ici :
sh$ ls -1 *.txt | cut -c 1-5
BALAN
BALAN
EMPTY
FILE
WITH
NAME.
Vous avez peut-être déjà lu ls
a été conçu pour la consommation humaine, et l'utiliser dans un pipeline de commandes est un anti-modèle (c'est en effet). Utilisons donc find
commande à la place :
sh$ find . -name '*.txt' -printf "%f\n" | cut -c 1-5
BALAN
EMPTY
FILE
WITH
NAME.
BALAN
et … qui produisait essentiellement le même résultat erroné qu'avant (bien que dans un ordre différent car ls
trie implicitement les noms de fichiers, quelque chose que le find
la commande ne le fait pas).
Le problème est dans les deux cas, le cut
La commande ne peut pas faire la distinction entre un caractère de saut de ligne faisant partie d'un champ de données (le nom de fichier) et un caractère de saut de ligne utilisé comme marqueur de fin d'enregistrement. Mais, en utilisant l'octet NUL (\0
) car le terminateur de ligne efface la confusion afin que nous puissions enfin obtenir le résultat attendu :
# I was told (?) some old versions of tr require using \000 instead of \0
# to denote the NUL character (let me know if you needed that change!)
sh$ find . -name '*.txt' -printf "%f\0" | cut -z -c 1-5| tr '\0' '\n'
BALAN
EMPTY
BALAN
Avec ce dernier exemple, nous nous éloignons du cœur de cet article qui était le cut
commande. Alors, je vous laisse essayer de comprendre par vous-même la signification du funky "%f\0"
après le -printf
argument du find
commande ou pourquoi j'ai utilisé le tr
commande à la fin du pipeline.
Beaucoup plus peut être fait avec la commande Couper
Je viens de montrer l'utilisation la plus courante et à mon avis la plus essentielle de la commande Couper. Vous pouvez appliquer la commande de manière encore plus pratique. Cela dépend de votre raisonnement logique et de votre imagination.
N'hésitez pas à utiliser la section des commentaires ci-dessous pour publier vos conclusions. Et, comme toujours, si vous aimez cet article, n'oubliez pas de le partager sur vos sites Web et réseaux sociaux préférés !