.png)
У меня есть следующий скрипт, который подсчитывает символы в пользовательском вводе:
echo -n "Type text: ";
read mystring;
echo -n $mystring | wc -m;
Без «-n» в последней строке количество символов было бы неверным, поскольку оно также включало бы символ новой строки, добавленный туда командой echo (поэтому количество символов, например, для «abc» было бы равно 4 вместо 3).
Ради практики я теперь хочу сделать эту коррекцию более сложным способом. Общая идея такова:
var=$($mystring | wc -m);
echo -n "Type text: ";
read mystring;
echo $(( $var - 1 ));
Итак, количество символов пользовательского ввода становится $var, а затем я вычитаю 1 из $var. Как мне заставить это работать?
решение1
Ваш скрипт не работает по нескольким причинам:
- Вы начинаете с инициализации,
var
чтобы она была равна выводу выполнения команды,| wc -m
посколькуmystring
на этом этапе она равна нулю. - Даже если бы он не был пустым, он попытался бы запустить его содержимое как команду и отправить этот вывод в
wc
.
Вам нужно A> делать вещи в правильном порядке и ii.> делать правильные вещи:
read -p "Type something > " mystring
var="$( wc -m <<< "$foo" )"
echo $(($var-1))
решение2
Если вы хотите подсчитать количество символов, введенных пользователем, не включая символ новой строки, то это должно быть так:
#! /bin/sh -
printf 'Type text: '
IFS= read -r userInput
length=$(printf %s "$userInput" | wc -m)
# or:
length=${#userInput}
Если вы хотите включить символ новой строки, который, возможно, ввел пользователь, то:
#! /bin/sh -
printf 'Type text: '
IFS= read -r userInput && userInput="$userInput
"
length=$(printf %s "$userInput" | wc -m)
# or:
length=${#userInput}
read
обычно возвращаетсяистинныйесли была введена полная строка (присутствует символ новой строки), поэтому мы добавляем единицу, если read
все прошло успешно.
Обратите внимание, что в большинстве реализаций оболочки ( zsh
за исключением случаев) она не будет работать правильно, если пользователь введет ^@
символ NUL (он же ).
Чтобы обойти это, вы можете сделать следующее:
printf 'Type text: '
length=$(line | wc -m)
Вместо этого. Или:
length=$(line | tr -d '\n' | wc -m)
# or
length=$(($(line | wc -m) - 1)) # as line always includes a newline on
# output even if one was not provided on
# input.
если вы не хотите учитывать перевод строки.
Поведение также будет отличаться, если пользователь введет байты, которые не являются частью допустимых символов. Вы также найдете некоторые sh
реализации, которые ${#var}
не работают должным образом с многобайтовыми символами (возвращают длину в байтах вместо символов).
решение3
expr " $mystring" : '.*' - 1
вернет длину содержимого переменной оболочкиmystring
решение4
В bash вы бы использовали
#!/usr/bin/env bash
read -p 'Type text: ' userInput
printf 'Your input was %d chars long\n' "${#userInput}"
Количество строк можно получить с помощью ${#var}
. Использование wc
в этом случае необязательно