Проверьте длину переменной

27

Я должен проверить длину чтения переменной (мой сценарий ограничен пятью вставленными символами), я думаю о чем-то вроде этого:

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

Есть ли более "элегантное" решение?

Пол Халлен
источник
1
Ваш скрипт корректно работает в стандартном POSIX /bin/sh. Вам следует подумать об изменении строки shebang, #!/bin/shчтобы она была более переносимой и работала в средах, где bash недоступен. Кроме того, это /bin/shможет быть более легкая оболочка, такая как dash, которая не обременена функциями, предназначенными для интерактивного использования.
Селада
@Celada, правда , хотя в данном случае, dash«s ${#string}даст вам длину в байтах , а не символы.
Стефан

Ответы:

43

Более элегантно? нет

Более короткие? Да :)

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

И если у вас нет проблем с тем, чтобы торговать более элегантно в пользу того, чтобы быть короче, у вас может быть скрипт на 2 строки меньше

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

Вы можете использовать двойные скобки, если считаете, что это безопаснее. Объяснение здесь .


источник
3

Bourne-совместимая альтернатива ( ${#string}это POSIX, но не Bourne (не то, чтобы вы когда-нибудь встречали оболочку Bourne в наши дни)):

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

Обратите внимание, что для обоих ${#string}и ????того, будет ли это число байтов или символов, будет зависеть от оболочки. Как правило (и это требуется POSIX), это количество символов. Но для некоторых таких оболочек, как dashэто не многобайтовый, вместо этого будут байты.

С помощью mkshвам set -o utf8-mode(в локалях UTF-8) нужно понимать многобайтовые символы:

$ 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
Стефан Шазелас
источник
не по теме, но echo Too longотличается под капотом отecho 'Too long'
Стивен Пенни
И, если вы будете просто печатать, когда он «слишком длинный», я могу if
2
@StevenPenny, echo Too longпередает два аргумента ( Tooи long), к echoкоторым выводятся, echoразделенные пробелом (и сопровождаемый символом новой строки), в то время как в echo 'Too long', мы передаем один Too longаргумент, echoкоторому он отображает после новой строки. Так что это функционально эквивалентно.
Стефан