Verifique o comprimento de uma variável

27

Eu tenho que verificar o comprimento da variável de leitura (meu script limita a cinco caracteres inseridos), penso em algo como isto:

#!/bin/bash
read string
check=${#string}
echo $check
if [ $check -ge 5 ]; then echo "error" ; exit
else echo "done"
fi

existe uma solução mais "elegante"?

Pol Hallen
fonte
11
Seu script funciona corretamente no POSIX padrão /bin/sh. Você deve alterar a linha shebang para #!/bin/shpara que fique mais portátil e execute em ambientes onde o bash não está disponível. Além disso, /bin/shpode ser um shell mais leve, como o dash, que não está sobrecarregado com os recursos destinados ao uso interativo.
Celada
@Celada, verdadeiro embora, neste caso, dash's ${#string}iria dar-lhe o comprimento em número de bytes em vez de caracteres.
Stéphane Chazelas

Respostas:

43

Mais elegante? Não

Mais curta? Sim :)

#!/bin/bash
read string
if [ ${#string} -ge 5 ]; then echo "error" ; exit
else echo "done"
fi

E se você não tiver nenhum problema em negociar mais elegância em favor de ser mais baixo, poderá ter um script com 2 linhas a menos:

#!/bin/bash
read string
[ ${#string} -ge 5 ] && echo "error" || echo "done"

Você pode usar colchetes duplos se achar que é mais seguro. Explicação aqui .


fonte
3

Uma alternativa compatível com Bourne ( ${#string}é POSIX, mas não Bourne (não é provável que você encontre um shell Bourne atualmente):

case $string in
  ?????*) echo >&2 Too long; exit 1;;
       *) echo OK
esac

Observe que para ambos ${#string}e ????, se será o número de bytes ou caracteres, dependerá do shell. Geralmente (e é exigido pelo POSIX), é o número de caracteres. Mas para alguns shells como dashesse não são compatíveis com vários bytes, serão bytes.

Com mksh, você precisa set -o utf8-mode(em localidades UTF-8) para entender caracteres de vários bytes:

$ string=€€€ bash -c 'echo "${#string}"'
3
$ string=€€€ dash -c 'echo "${#string}"'
9
$ string=€€€ mksh -c 'echo "${#string}"'
9
$ string=€€€ mksh -o utf8-mode -c 'echo "${#string}"'
3
$ locale charmap
UTF-8
Stéphane Chazelas
fonte
fora do assunto, mas é echo Too longdiferente sob o capô deecho 'Too long'
Steven Penny
E, se você só vai imprimir quando é "muito longo", eu posso compactar ainda mais no meu ifopção :)
2
@StevenPenny, echo Too longpassa dois argumentos ( Tooe long) para os echoquais as echosaídas são separadas por um espaço (e seguidas por uma nova linha), enquanto dentro echo 'Too long', passamos um Too longargumento para o echoqual ele é exibido após uma nova linha. Portanto, é funcionalmente equivalente.
Stéphane Chazelas