Saisir les [x] premiers caractères d'une chaîne à partir d'un tuyau

58

Si j'ai une très longue sortie d'une commande (une seule ligne) mais que je sais que je ne veux que les premiers [x] (disons 8) caractères de la sortie, quel est le moyen le plus simple de l'obtenir? Il n'y a pas de délimiteurs.

xénoterracide
la source
related: stackoverflow.com/questions/1405611/…
Ciro Santilli a ajouté la marque

Réponses:

82

Une façon est d'utiliser cut:

 command | cut -c1-8

Cela vous donnera les 8 premiers caractères de chaque ligne de sortie. Étant donné qu’il cutfait partie de POSIX, il est susceptible de figurer sur la plupart des Unices.

Steven D
la source
3
Notez que cut -csélectionne les caractères; cut -bou head -csélectionne des octets. Cela fait une différence dans certains endroits (en pratique, lorsque vous utilisez UTF-8).
Gilles 'SO- arrête d'être méchant'
Vous n'avez pas non plus à spécifier l'index de départ dans ce cas. Saying cut -c-8choisira parmi les caractères 1 à 8.
Sparhawk
@Steven, cutl'équivalent sous Windows est?
Pacerier
Aussi command | dd bs=8 count=1 2>/dev/null. Ne dis pas que c'est plus court ou supérieur. Juste une autre alternative.
dubiousjim
@Gilles, mais notez qu'avec les versions actuelles de GNU cut, cut -cfonctionne comme cut -b( autrement dit, cela ne fonctionne pas correctement pour les caractères multi-octets).
Stéphane Chazelas
24

Voici quelques autres moyens pour n’obtenir que les 8 premiers caractères.

command | head -c8

command | awk '{print substr($0,1,8);exit}' 

command | sed 's/^\(........\).*/\1/;q'

Et si tu as bash

var=$(command)
echo ${var:0:8}
utilisateur1606
la source
2
Je pense que la formulation sed suivante est un peu plus facile à lire: command | sed 's/\(.\{8\}\).*/\1/'ou si vos supports sed il: command | sed -r 's/(.{8}).*/\1/'; Sinon, +1
Steven D
Bien, mais notez que cela head -ccompte en octets , pas en caractères. De même, parmi les principales implémentations d'Awk, seul GNU awk gère correctement les caractères multi-octets - FreeBSD Awk et Mawk ne le font pas.
mklement0
2

Si vous avez un shell suffisamment avancé (par exemple, ce qui suit fonctionnera dans Bash, vous n'êtes pas certain du tiret), vous pouvez le faire:

read -n8 -d$'\0' -r <(command)

Après exécution read ... <(command), vos personnages seront dans la variable shell REPLY. Tapez help readpour en savoir plus sur les autres options.

Explication: l' -n8argument à readqui indique que nous voulons 8 caractères maximum. Le -d$'\0'dit lu jusqu'à null, plutôt que sur une nouvelle ligne. De cette façon, la lecture continuera pour 8 caractères même si l’un des caractères précédents est une nouvelle ligne (mais pas si c’est nul). Une alternative à -n8 -d$'\0'est d'utiliser -N8, qui lit exactement 8 caractères ou jusqu'à ce que le stdin atteigne EOF. Aucun délimiteur n'est honoré. Cela répond probablement mieux à vos besoins, mais je ne sais pas au juste combien de coquilles ont une lecture qui honore -Npar opposition à honorer -net -d. Continuant avec l'explication: -rdit ignorer \-escapes, de sorte que, par exemple, nous traitons \\comme deux caractères plutôt que comme un seul \.

Enfin, nous le faisons read ... <(command)plutôt que command | read ...parce que dans la seconde forme, la lecture est exécutée dans un sous-shell qui est ensuite immédiatement quitté, perdant ainsi les informations que vous venez de lire.

Une autre option consiste à effectuer tous vos traitements dans le sous-shell. Par exemple:

$ echo abcdefghijklm | { read -n8 -d$'\0' -r; printf "REPLY=<%s>\n" "$REPLY"; }
REPLY=<abcdefgh>
douteux
la source
1
Si vous voulez simplement sortir les 8 caractères et n'avez pas besoin de les traiter dans le shell, utilisez simplement cut.
dubiousjim
Bon à savoir sur read -n <num>; petite mise en garde: Bash 3.x (toujours en cours sur le système d'exploitation) interprète à tort <num>comme un nombre d' octets et échoue donc avec les caractères multi-octets; cela a été corrigé dans Bash 4.x.
mklement0
C'est une excellente et utile réponse. Beaucoup plus général que les autres.
not2qubit
2

Une autre solution one-liner utilisant l' expansion des paramètres

echo ${word:0:x}

EG: word="Hello world"
echo ${word:0:3} or echo ${word::3} 
o/p: Hel


EG.2: word="Hello world"
echo ${word:1:3}
o/p: ell
Prabhat Kumar Singh
la source
Vous pouvez également utiliser une variable contenant la longueur, par exemple: x=8; echo ${word:0:$x}au lieu de coder en dur le nombre entier.
Cometsong
1

C'est portable:

a="$(command)"             # Get the output of the command.
b="????"                   # as many ? as characters are needed.
echo ${a%"${a#${b}}"}      # select that many chars from $a

Construire une chaîne de caractères de longueur variable a sa propre question ici .

Communauté
la source
0

J'ai eu ce problème lors de la génération manuelle de fichiers de somme de contrôle dans le référentiel maven. Malheureusement cut -c, une nouvelle ligne est toujours imprimée à la fin de la sortie. Pour supprimer que j'utilise xxd:

command | xxd -l$BYTES | xxd -r

Il affiche exactement les $BYTESoctets, sauf si la commandsortie de est plus courte, alors exactement cette sortie.

Krzysztof Jabłoński
la source
une autre méthode pour décoller de cutla nouvelle ligne est de la | tr -d '\n'
transférer