Bash
La commande de coupe
Recherche…
Introduction
La commande cut
est un moyen rapide d'extraire des parties de lignes de fichiers texte. Il appartient aux plus anciennes commandes Unix. Ses implémentations les plus populaires sont la version GNU trouvée sur Linux et la version FreeBSD disponible sur MacOS, mais chaque version d'Unix a la sienne. Voir ci-dessous pour les différences. Les lignes d'entrée sont lues à partir de stdin
ou de fichiers répertoriés comme arguments sur la ligne de commande.
Syntaxe
cut -f1,3 # extrait le premier et le troisième champ délimité par des tabulations (à partir de stdin)
cut -f1-3 # extrait du premier au troisième champ (extrémités incluses)
cut -f-3 # -3 est interprété comme 1-3
cut -f2- # 2 est interprété de la seconde au dernier
cut -c1-5,10 # extrait de stdin les personnages dans les positions 1,2,3,4,5,10
cut -s -f1 # supprime les lignes ne contenant pas de délimiteurs
cut --complement -f3 # (coupe GNU uniquement) extrait tous les champs sauf le troisième
Paramètres
Paramètre | Détails |
---|---|
-f, --fields | Sélection par champs |
-d, --delimiter | Délimiteur pour la sélection par champs |
-c, --characters | Sélection basée sur les caractères, délimiteur ignoré ou erreur |
-s, - uniquement délimité | Supprimer les lignes sans caractère de délimitation (imprimé tel quel) |
--complément | Sélection inversée (extraire tout sauf les champs / caractères spécifiés |
--distributeur de sortie | Indiquez quand il doit être différent du délimiteur d'entrée |
Remarques
1. Différences de syntaxe
Les options longues du tableau ci-dessus ne sont prises en charge que par la version GNU.
2. Aucun personnage ne bénéficie d'un traitement spécial
FreeBSD cut
(fourni avec MacOS, par exemple) ne possède pas le commutateur --complement
et, dans le cas des plages de caractères, on peut utiliser la commande colrm
place:
$ cut --complement -c3-5 <<<"123456789"
126789
$ colrm 3 5 <<<"123456789"
126789
Cependant, il y a une grande différence, car colrm
traite les caractères TAB (ASCII 9) comme des tabulations réelles jusqu'au multiple de huit suivant, et les backspaces (ASCII 8) de -1; au contraire, cut
traite tous les caractères comme une colonne de large.
$ colrm 3 8 <<<$'12\tABCDEF' # Input string has an embedded TAB
12ABCDEF
$ cut --complement -c3-8 <<<$'12\tABCDEF'
12F
3. (Toujours pas) l'internationalisation
Lorsque la cut
été conçue, tous les caractères duraient un octet et l’internationalisation n’était pas un problème. Lorsque les systèmes d’écriture avec des caractères plus larges sont devenus populaires, la solution adoptée par POSIX consistait à distinguer l’ancien commutateur -c
, qui devrait conserver son sens de la sélection des caractères, peu importe le nombre d’octets, et introduire un nouveau commutateur -b
sélectionnez des octets, quel que soit le codage de caractères actuel. Dans les implémentations les plus courantes, -b
été introduit et fonctionne, mais -c
fonctionne toujours exactement comme -b
et pas comme il le devrait. Par exemple avec GNU cut
:
Il semble que le filtre anti-spam de SE liste les textes anglais avec des caractères kanji isolés. Je ne pouvais pas surmonter cette limitation, alors les exemples suivants sont moins expressifs qu'ils pourraient l'être.
# In an encoding where each character in the input string is three bytes wide,
# Selecting bytes 1-6 yields the first two characters (correct)
$ LC_ALL=ja_JP.UTF-8 cut -b1-6 kanji.utf-8.txt
...first two characters of each line...
# Selecting all three characters with the -c switch doesn’t work.
# It behaves like -b, contrary to documentation.
$ LC_ALL=ja_JP.UTF-8 cut -c1-3 kanji.utf-8.txt
...first character of each line...
# In this case, an illegal UTF-8 string is produced.
# The -n switch would prevent this, if implemented.
$ LC_ALL=ja_JP.UTF-8 cut -n -c2 kanji.utf-8.txt
...second byte, which is an illegal UTF-8 sequence...
Si vos personnages sont en dehors de la plage ASCII et que vous voulez utiliser cut
, vous devez toujours être au courant de la largeur des caractères dans l' encodage et utilisez -b
en conséquence. Si et quand -c
commence à fonctionner comme documenté, vous n'aurez pas à modifier vos scripts.
4. Comparaisons de vitesse
Les restrictions de cut
ont des doutes sur son utilité. En fait, les mêmes fonctionnalités peuvent être obtenues par des utilitaires plus puissants et plus populaires. Cependant, l'avantage de la cut
est sa performance . Voir ci-dessous pour des comparaisons de vitesse. test.txt
a trois millions de lignes, chacune contenant cinq champs séparés par des espaces. Pour le test awk
, mawk
été utilisé, car il est plus rapide que GNU awk
. Le shell lui-même (dernière ligne) est de loin le moins performant. Les temps donnés (en secondes) sont ce que la commande de time
donne en temps réel .
(Juste pour éviter les malentendus: toutes les commandes testées donnaient la même sortie avec l'entrée donnée, mais elles ne sont bien sûr pas équivalentes et donneraient des sorties différentes dans des situations différentes, notamment si les champs étaient délimités par un nombre variable d'espaces)
Commander | Temps |
---|---|
cut -d ' ' -f1,2 test.txt | 1.138s |
awk '{print $1 $2}' test.txt | 1.688s |
join -a1 -o1.1,1.2 test.txt /dev/null | 1.767s |
perl -lane 'print "@F[1,2]"' test.txt | 11.390s |
grep -o '^\([^ ]*\) \([^ ]*\)' test.txt | 22.925s |
sed -e 's/^\([^ ]*\) \([^ ]*\).*$/\1 \2/' test.txt | 52.122s |
while read ab _; do echo $a $b; done <test.txt | 55.582s |
5. Pages de manuel référentielles
Utilisation de base
L'utilisation typique est avec les fichiers de type CSV, où chaque ligne est composée de champs séparés par un délimiteur, spécifié par l'option -d
. Le délimiteur par défaut est le caractère de tabulation. Supposons que vous ayez un fichier de données data.txt
avec des lignes comme
0 0 755 1482941948.8024
102 33 4755 1240562224.3205
1003 1 644 1219943831.2367
alors
# extract the third space-delimited field
$ cut -d ' ' -f3 data.txt
755
4755
644
# extract the second dot-delimited field
$ cut -d. -f2 data.txt
8024
3205
2367
# extract the character range from the 20th through the 25th character
$ cut -c20-25 data.txt
948.80
056222
943831
Comme d'habitude, il peut y avoir des espaces optionnels entre un switch et son paramètre: -d,
est le même que -d ,
GNU cut
permet de spécifier une option --output-delimiter
: (une caractéristique indépendante de cet exemple est qu'un point-virgule en tant que délimiteur d'entrée doit être échappé pour éviter son traitement spécial par le shell)
$ cut --output-delimiter=, -d\; -f1,2 <<<"a;b;c;d"
a,b
Un seul caractère délimiteur
Vous ne pouvez pas avoir plus d'un delimiter: si vous spécifiez quelque chose comme -d ",;:"
, certaines implémentations utiliseront uniquement le premier caractère comme séparateur (. Dans ce cas, la virgule) Autres mises en œuvre (par exemple GNU cut
) donnera vous un message d'erreur.
$ cut -d ",;:" -f2 <<<"J.Smith,1 Main Road,cell:1234567890;land:4081234567"
cut: the delimiter must be a single character
Try `cut --help' for more information.
Les délimiteurs répétés sont interprétés comme des champs vides
$ cut -d, -f1,3 <<<"a,,b,c,d,e"
a,b
est assez évident, mais avec des chaînes délimitées par des espaces, il pourrait être moins évident pour certains
$ cut -d ' ' -f1,3 <<<"a b c d e"
a b
cut
ne peut pas être utilisé pour analyser les arguments comme le font le shell et les autres programmes.
Aucun devis
Il n'y a aucun moyen de protéger le délimiteur. Les feuilles de calcul et les logiciels de gestion de CSV similaires peuvent généralement reconnaître un caractère de citation de texte qui permet de définir des chaînes contenant un délimiteur. Avec la cut
vous ne pouvez pas.
$ cut -d, -f3 <<<'John,Smith,"1, Main Street"'
"1
Extraire, ne pas manipuler
Vous ne pouvez extraire que des parties de lignes, pas réorganiser ni répéter des champs.
$ cut -d, -f2,1 <<<'John,Smith,USA' ## Just like -f1,2
John,Smith
$ cut -d, -f2,2 <<<'John,Smith,USA' ## Just like -f2
Smith