Extraction de caractères : cut

La commande cut sert à récupérer des caractères ou des champs d'une ligne.

Syntaxe

Couper par caractères

cut -c3 [fichiers ...] Le 3ème caractère
cut -c3-5 [fichiers ...] Du 3ème au 5ème caractère
cut -c-3 [fichiers ...] Jusqu'au 3ème caractère
cut -c3- [fichiers ...] A partir du 3ème caractère
cut -c3,10 [fichiers ...] Le 3ème et le 10ème caractère

Couper par champs

cut -dsep -f3 [fichiers ...] Le 3ème champ
cut -dsep -f3-5 [fichiers ...] Du 3ème au 5ème champ
cut -dsep -f-3 [fichiers ...] Jusqu'au 3ème champ
cut -dsep -f3- [fichiers ...] A partir du 3ème champ
cut -dsep -f3,10 [fichiers ...] Le 3ème et le 10ème champ

L'option -d permet d'exprimer le caractère séparateur de champ. Le caractère séparateur par défaut est la tabulation.

Exemples

Couper les 2 Premiers chiffres d'un code postal

$ echo 44150 | cut -c1-2
44
$

Afficher le 1er, 6ème et 7ème champs des 5 dernières lignes du fichier /etc/passwd

$ tail -5 /etc/passwd | cut -d: -f1,6,7
nobody:/nonexistent:/bin/sh
libuuid:/var/lib/libuuid:/bin/sh
postfix:/var/spool/postfix:/bin/false
sshd:/var/run/sshd:/usr/sbin/nologin
mysql:/var/lib/mysql:/bin/false
$

Si le caractère séparateur est un caractère spécial du shell, il faut le protéger.

$ ligne="val1|val2|val3"
$ echo $ligne | cut -d'|' -f1
val1
$

Etiquettes: 

Commentaires

merci beaucoup

J'aimerais Afficher dans chaque ligne les cinq premiers caracteres et les trois derniers caracteres de chaque ligne de mon fichier texte en les separant par un espace.

Bonjour,

Pour ton problème, je te propose d'utiliser à la place de la commande cut, la commande sed.

Exemple:

$ sed -r 's/^(.{5}).*(.{3})$/\1 \2/' <fichier>

Explications:

La commande sed permet de modifier le contenu d'un fichier à l'aide de regex.
L'option -r permet d'utiliser les regex étendues.
La commande s/regexp/replacement/ substitue le contenu du fichier par replacement en utilisant la regex regexp.
Je te renvoie ici pour plus d'explications sur la commande sed.

Bonjour,

Est-il possible de faire la même opération mais de sélectionner des colonnes et non des caractères?

merci

si tes champs sont de longueurs fixes ou avec un séparateur.

Par exemple, avec ce fichier (je pars du principe que j'ai 6 champs de longueurs fixes [5,10,10,1,3,10]):

$ cat file
Borne012345678901234567890AAA0123456789
Corne012345678901234567890AAA0123456789
Dorne012345678901234567890AAA0123456789
Borne012345678901234567890AAA0123456789
Eorne012345678901234567890AAA0123456789
Borne012345678901234567890AAA0123456789
Forne012345678901234567890AAA0123456789
Gorne012345678901234567890AAA0123456789
Horne012345678901234567890AAA0123456789
Iorne012345678901234567890AAA0123456789
Borne012345678901234567890AAA0123456789
Borne012345678901234567890AAA0123456789
Borne012345678901234567890AAA0123456789
Borne012345678901234567890AAA0123456789
Jorne012345678901234567890AAA0123456789

Je peux faire ceci:

$ sed -r 's/^(.{5})(.{10})(.{10})(.)(.{3})(.{10})$/\1 \2 \3 \4 \5 \6/g' file
Borne 0123456789 0123456789 0 AAA 0123456789
Corne 0123456789 0123456789 0 AAA 0123456789
Dorne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Eorne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Forne 0123456789 0123456789 0 AAA 0123456789
Gorne 0123456789 0123456789 0 AAA 0123456789
Horne 0123456789 0123456789 0 AAA 0123456789
Iorne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Jorne 0123456789 0123456789 0 AAA 0123456789

ou alors avec un fichier ayant un séparateur de champ ";"

$ cat file2
Borne;0123456789;0123456789;0;AAA;0123456789
Corne;0123456789;0123456789;0;AAA;0123456789
Dorne;0123456789;0123456789;0;AAA;0123456789
Borne;0123456789;0123456789;0;AAA;0123456789
Eorne;0123456789;0123456789;0;AAA;0123456789
Borne;0123456789;0123456789;0;AAA;0123456789
Forne;0123456789;0123456789;0;AAA;0123456789
Gorne;0123456789;0123456789;0;AAA;0123456789
Horne;0123456789;0123456789;0;AAA;0123456789
Iorne;0123456789;0123456789;0;AAA;0123456789
Borne;0123456789;0123456789;0;AAA;0123456789
Borne;0123456789;0123456789;0;AAA;0123456789
Borne;0123456789;0123456789;0;AAA;0123456789
Borne;0123456789;0123456789;0;AAA;0123456789
Jorne;0123456789;0123456789;0;AAA;0123456789
$ sed -r 's/;/ /g' file2
Borne 0123456789 0123456789 0 AAA 0123456789
Corne 0123456789 0123456789 0 AAA 0123456789
Dorne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Eorne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Forne 0123456789 0123456789 0 AAA 0123456789
Gorne 0123456789 0123456789 0 AAA 0123456789
Horne 0123456789 0123456789 0 AAA 0123456789
Iorne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Borne 0123456789 0123456789 0 AAA 0123456789
Jorne 0123456789 0123456789 0 AAA 0123456789

 

sed ne fonctionnera pas si plus de 9 champs à extraire ;-( any other solution ?

un script Python fera très bien l'affaire.

Bonjour,
J'ai besoin d'extraire une partie d'une variable à partir du 2ème caractères jusqu'à la fin de la variable.
Pour cela j'utilise, par exemple:
var=-136.5
var2=`echo $var | cut -c 2-${#var}`
echo $var2 donne: 136 5 donc pas de problème.

Mais lorsque je l'utilise dans un script, la variable "longueur" dans la commande cut n'est pas prise en compte:
cut: invalid byte, character or field list
Try `cut --help' for more information

Si le 2ème chiffre dans la commande est écrit en "dur", pas de problème dans le script, mais vu que mes variables n'ont pas toutes la même longueur, j'ai besoin d'utiliser la longueur de la variable dans la commande...mais là impossible...

Pouvez-vous m'aider?

Merci!

Bonjour,

L'erreur que vous avez est bizarre car j'ai effectué un test de mon coté et ça fonctionne correctement.

Toujours est-il que comme indiqué à la quatrième ligne du tableau "Couper par caractères", dans le cas où l'on souhaite extraire tout le restant de la chaine, il n'est pas nécessaire d'indiquer une position de fin.
Cela réglera votre problème malgré que de mon coté ça fonctionne bien.

Voici le script que j'ai écrit pour le test

$ cat test
#!/bin/bash
# Permet d'activer les logs lors de l'exécution
set -x

echo "Init variable A"
A=-136.5
echo "Longueur de la variable A"
B=${#A}
echo "Premier cut sans indiquer la dernière position"
C=`echo $A | cut -c2-`
echo "Second cut en indiquant la dernière position"
D=`echo $A | cut -c2-${#A}`

Voici le résultat

$ ./test
+ echo 'Init variable A'
Init variable A
+ A=-136.5
+ echo 'Longueur de la variable A'
Longueur de la variable A
+ B=6
+ echo 'Premier cut sans indiquer la dernière position'
Premier cut sans indiquer la dernière position
++ echo -136.5
++ cut -c2-
+ C=136.5
+ echo 'Second cut en indiquant la dernière position'
Second cut en indiquant la dernière position
++ echo -136.5
++ cut -c2-6
+ D=136.5

Dans le résultat de l'exécution, on voit bien que les deux cut ont fonctionné comme voulu.
Les deux variables C et D ont la même valeur.
Il peut s'agir d'une erreur toute bête dans votre script.
Pour le vérifier, pensez à activer le debug du script avec la commande "set -x".
C'est vraiment super pratique pour voir où il y a un bug.

Bonjour,

Merci de votre réponse.
Effectivement sans renseigner la position de fin cela fonctionne très bien.
Je n'avais tout simplement pas d'erreur, car en console cela fonctionnait mais pas en script. Mes variables étant alimentées par résultat de requête SQL dans le script, il arrivait qu'un résultat soit null, dans ce cas la longueur de la variable est 0 et un cut -c 2-0 n'est bien évidemment pas accepté...
Excusez mon erreur!

Bien cordialement

bonjour, je souhaite vous demander de l'aide svp je débute en shell
je vous remercie d'avnce

Je pense que tout le contenu concernant Bash est assez bien documenté pour commencer

J'aimerais dans un log recuperer tout les segments compris entre 2 mots précis. Est ce possible ?

Bonjour Frédéric
Aurais tu un exemple à fournir ?

Oui voici un exemple :

Emetteur
Entrée A
Entrée B
Dossier modifie

Emetteur
Entrée C
Entrée D
Dossier inconnu

Emetteur
Entrée A
Entrée C
Dossier modifie

Emetteur
Entrée B
Entrée X
Dossier inconnu

Voilà, ce que je souhaiterais, c'est ne garder que les dossiers inconnus :

Emetteur
Entrée C
Entrée D
Dossier inconnu

Emetteur
Entrée B
Entrée X
Dossier inconnu

Le problème étant que faire un cat Fichier.log | awk '/Emetteur/,/Dossier inconnu/' > DossierInconnu.log ne suffit pas, car il me prend trop de chose.

$ tac Fichier.log | sed -n '/Dossier inconnu/,/Emetteur/p' | tac
Emetteur
Entrée C
Entrée D
Dossier inconnu
Emetteur
Entrée B
Entrée X
Dossier inconnu

Merci Ronan,
J'ai réussi a le faire avec awk au final, je partage l'info au cas ou ça intéresse du monde ici :
awk '/^Emetteur/{n=1} {lines[n++]=$0} /^Dossier inconnu/{for(i=1;i<n;++i) print lines[i]}' Event.log

juste pour info, le "|tac" a la fin de ton sed sert a faire quoi s'il te plait ?

J'ai pas eu le temps de tester ta solution.
Pour ce qui est de la mienne, le premier "tac" permet d'inverser le contenu du fichier, de cette façon, il est plus simple de trouver en premier "Dossier inconnu" étant donné que tous les blocs d'information commencent tous par "Emetteur" et enfin, pour finir, le deuxième et dernier "tac" permet de remettre dans le bon ordre les éléments trouvés.

Merci Ronan !

Ajouter un commentaire

Filtered HTML

  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.
  • Tags HTML autorisés : <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Les lignes et les paragraphes vont à la ligne automatiquement.

Plain text

  • Aucune balise HTML autorisée.
  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.
  • Les lignes et les paragraphes vont à la ligne automatiquement.
CAPTCHA
Cette question permet de s'assurer que vous êtes un utilisateur humain et non un logiciel automatisé de pollupostage.
CAPTCHA visuel
Entrez les caractères (sans espace) affichés dans l'image.