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


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow