Упражнение по подсчету символов (bash)

Упражнение по подсчету символов (bash)

У меня есть следующий скрипт, который подсчитывает символы в пользовательском вводе:

    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в этом случае необязательно

Связанный контент