574 votes

Longueur de la chaîne en bash

Comment obtenir la longueur d'une chaîne de caractères stockée dans une variable et l'affecter à une autre variable ?

myvar="some string"
echo ${#myvar}  
# 11

Comment définir une autre variable à la sortie 11 ?

617voto

fedorqui Points 42938

Pour obtenir la longueur d'une chaîne de caractères stockée dans une variable, par exemple :

myvar="some string"
size=${#myvar} 

Pour confirmer qu'il a été correctement enregistré, echo il :

$ echo "$size"
11

14 votes

Avec les chaînes UTF-8, vous pourriez avoir une longueur de chaîne de caractères et une longueur d'octets. voir ma réponse

1 votes

Vous pouvez également l'utiliser directement dans d'autres expansions de paramètres - par exemple dans ce test je vérifie que $rulename commence par le $RULE_PREFIX préfixe : [ "${rulename:0:${#RULE_PREFIX}}" == "$RULE_PREFIX" ]

2 votes

Pourriez-vous expliquer un peu les expressions de #myvar y {#myvar} ?

366voto

F. Hauri Points 5893

Longueur de la chaîne UTF-8

En plus de La réponse correcte de fedorqui Je voudrais montrer la différence entre chaîne de caractères longueur et octet longueur :

myvar='Généralités'
chrlen=${#myvar}
oLang=$LANG oLcAll=$LC_ALL
LANG=C LC_ALL=C
bytlen=${#myvar}
LANG=$oLang LC_ALL=$oLcAll
printf "%s is %d char len, but %d bytes len.\n" "${myvar}" $chrlen $bytlen

rendra :

Généralités is 11 char len, but 14 bytes len.

vous pourriez même jeter un coup d'oeil aux caractères stockés :

myvar='Généralités'
chrlen=${#myvar}
oLang=$LANG oLcAll=$LC_ALL
LANG=C LC_ALL=C
bytlen=${#myvar}
printf -v myreal "%q" "$myvar"
LANG=$oLang LC_ALL=$oLcAll
printf "%s has %d chars, %d bytes: (%s).\n" "${myvar}" $chrlen $bytlen "$myreal"

répondra :

Généralités has 11 chars, 14 bytes: ($'G\303\251n\303\251ralit\303\251s').

Nota : Selon Commentaire d'Isabell Cowan J'ai ajouté un paramètre à $LC_ALL ainsi que $LANG .

Longueur d'un argument, échantillon de travail

Les arguments fonctionnent comme les variables ordinaires

showStrLen() {
    local bytlen sreal oLang=$LANG oLcAll=$LC_ALL
    LANG=C LC_ALL=C
    bytlen=${#1}
    printf -v sreal %q "$1"
    LANG=$oLang LC_ALL=$oLcAll
    printf "String '%s' is %d bytes, but %d chars len: %s.\n" "$1" $bytlen ${#1} "$sreal"
}

fonctionnera comme

showStrLen théorème
String 'théorème' is 10 bytes, but 8 chars len: $'th\303\251or\303\250me'

Utile printf outil de correction :

Si vous :

for string in Généralités Language Théorème Février  "Left: ←" "Yin Yang ☯";do
    printf " - %-14s is %2d char length\n" "'$string'"  ${#string}
done

 - 'Généralités' is 11 char length
 - 'Language'     is  8 char length
 - 'Théorème'   is  8 char length
 - 'Février'     is  7 char length
 - 'Left: ←'    is  7 char length
 - 'Yin Yang ☯' is 10 char length

Pas vraiment. joli sortie !

Pour cela, voici une petite fonction :

strU8DiffLen() {
    local charlen=${#1} LANG=C LC_ALL=C
    return $(( ${#1} - charlen ))
}

ou écrit en une seule ligne :

strU8DiffLen() { local chLen=${#1} LANG=C LC_ALL=C;return $((${#1}-chLen));}

Alors maintenant :

for string in Généralités Language Théorème Février  "Left: ←" "Yin Yang ☯";do
    strU8DiffLen "$string"
    printf " - %-$((14+$?))s is %2d chars length, but uses %2d bytes\n" \
        "'$string'" ${#string} $((${#string}+$?))
  done 

 - 'Généralités'  is 11 chars length, but uses 14 bytes
 - 'Language'     is  8 chars length, but uses  8 bytes
 - 'Théorème'     is  8 chars length, but uses 10 bytes
 - 'Février'      is  7 chars length, but uses  8 bytes
 - 'Left: ←'      is  7 chars length, but uses  9 bytes
 - 'Yin Yang ☯'   is 10 chars length, but uses 12 bytes

Malheureusement, ce n'est pas parfait !

Mais il restait quelques comportements étranges de l'UTF-8, comme les caractères à double espacement, les caractères à espacement nul, le déplacement inverse et d'autres qui ne pouvaient pas être aussi simples...

Jetez un coup d'œil à diffU8test.sh o diffU8test.sh.txt pour plus de limitations.

0 votes

J'apprécie cette réponse, car les systèmes de fichiers imposent des limitations de noms en octets et non en caractères.

2 votes

Vous devrez peut-être aussi définir LC_ALL=C et peut-être d'autres.

0 votes

@IsabellCowan Dans quel cas ? Je pense que non ! Vous pourriez préférer utiliser LC_ALL mais s'il n'est pas utilisé, ce n'est pas nécessaire . Mais aucune autre variable ne doit être utilisée.

44voto

dmatej Points 345

Je voulais le cas le plus simple, finalement c'est un résultat :

echo -n 'Tell me the length of this sentence.' | wc -m;
36

7 votes

Désolé mon pote :( C'est Bash... le marteau maudit qui voit tout comme un clou, particulièrement votre pouce. "Dites-moi la longueur de cette phrase." contient 36 caractères. echo '' | wc -m => 1 . Vous devez utiliser -n : echo -n '' | wc -m => 0 ... dans ce cas, c'est une bonne solution :)

2 votes

Merci pour la correction ! La page du manuel dit : -n do not output the trailing newline

27voto

atesin Points 283

Vous pouvez utiliser :

MYSTRING="abc123"
MYLENGTH=$(printf "%s" "$MYSTRING" | wc -c)
  • wc -c o wc --bytes pour les comptes d'octets = les caractères Unicode sont comptés avec 2, 3 ou plus d'octets.
  • wc -m o wc --chars pour le nombre de caractères = les caractères Unicode sont comptés individuellement jusqu'à ce qu'ils utilisent plus d'octets.

4 votes

3 votes

Sérieusement ? un tuyau, un sous-shell et une commande externe pour quelque chose d'aussi trivial ?

0 votes

Cela gère quelque chose comme mylen=$(printf "%s" "$HOME/.ssh" | wc -c) alors que la solution acceptée échoue et que vous devez myvar=$HOME/.ssh d'abord.

21voto

JGFMK Points 405

En réponse au post de départ :

Si vous voulez l'utiliser avec des arguments de ligne de commande ou de fonction...

avec le code :

size=${#1}

Il peut arriver que vous souhaitiez simplement vérifier si un argument est de longueur nulle et que vous n'ayez pas besoin de stocker une variable. Je crois que vous pouvez utiliser ce genre de syntaxe :

if [ -z "$1" ]; then
    #zero length argument 
else
    #non-zero length
fi

Voir GNU y wooledge pour une liste plus complète des expressions conditionnelles Bash.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X