2013-02-27 3 views
23

Я хочу подсчитать количество слов из строки, используя оболочку.Как подсчитать количество слов из строки с помощью оболочки

Пусть Строка:

input="Count from this String" 

Здесь разделитель пространство ' ' и ожидаемый выход 4. Там также может быть трейлинг символы пробела в строке ввода, как "Count from this String ".

Если в строке есть конечное пространство, он должен выдавать тот же результат, что и 4. Как я могу это сделать?

+1

Почему downvote вопрос? Или это означает, что, если кто-то не знает чего-то, а другие знают об этом, тогда они могут просто понижать уровень. –

ответ

30
echo "$input" | wc -w 

Используйте wc-w для подсчета количества слов.

Или согласно предложению кендырь, в эхо может быть избавились, а также:

wc -w <<< "$input" 

Если < < < не поддерживается вашей оболочки, вы можете попробовать этот вариант:

wc -w << END_OF_INPUT 
$input 
END_OF_INPUT 
+6

Это [бесполезное использование эха] (http://fahdshariff.blogspot.com/2012/12/useless-use-of-echo.html).Вместо этого используйте 'wc -w <<<" $ input ". – dogbane

+0

Спасибо Tuxdude и dogbane за ваши ответы. Если я использую wc -w <<< "$ input", я получаю сообщение об ошибке: ** Синтаксическая ошибка: получил <&, ожидая Word **. Есть идеи? –

+0

Какую оболочку вы используете? – Tuxdude

27

Вам не нужна внешняя команда, например wc, потому что вы можете сделать это в чистом bash, что более эффективно.

Преобразование строки в массив, а затем подсчет элементов в массиве:

$ input="Count from this String " 
$ words=($input) 
$ echo ${#words[@]} 
4 

В качестве альтернативы, использовать set установить позиционные параметры, а затем сосчитать их:

$ input="Count from this String " 
$ set -- $input 
$ echo $# 
4 
+3

Второй вариант имеет побочный эффект: он перезаписывает позиционные параметры, такие как любые полученные из командной строки или параметры, переданные функции (если эти строки находятся в пределах функции). Поэтому не стоит полагаться на $ 1, $ 2 и т. Д. После использования set - $ input – Tuxdude

+0

@Tuxdude Это было очень важно. Спасибо –

+0

@dogbane Второе предложенное вами решение отлично работает для меня, но, как указал Tuxdude, я не могу заменить существующие параметры новым, поскольку он нарушит текущий поток. Я попытался реализовать первое решение, но, к сожалению, я получаю сообщение об ошибке: ** Синтаксическая ошибка: got (, ожидание Newline ** –

5

Чтобы сделать это в чистый баш, избегая побочных эффектов, делать это в подколе:

$ input="Count from this string " 
$ echo $(IFS=' '; set -f; set -- $input; echo $#) 
4 

Он работает с другими сепараторами, а также:

$ input="dog,cat,snake,billy goat,horse" 
$ echo $(IFS=,; set -f; set -- $input; echo $#) 
5 
$ echo $(IFS=' '; set -f; set -- $input; echo $#) 
2 

Обратите внимание на использование «установите -f», который отключает bash filename expansion в субоболочке, так что, если абонент хочет расширения это должно быть сделано заранее (Hat Tip @ mkelement0).

+2

Красиво сделано, я предлагаю добавлять 'set -f;' каждой команде 'set' (примечание: должно быть _separate_), чтобы (временно) отключить расширение пути. Это гарантирует, что входные токены, такие как '*', не были случайно расширены. – mklement0

3

Попробуйте следующий один вкладыш:

echo $(c() { echo $#; }; c $input) 

Это в основном определяет c() функцию и передает $input в качестве аргумента, а затем $# возвращает количество элементов в аргументе разделенных пробелами. Чтобы изменить разделитель, вы можете изменить IFS (специальная переменная).

3
echo "$input" | awk '{print NF}' 
+0

Мне нравится, что с 'NF-x', где x - любое число, вы можете удалить которые не учитываются. – PdC

0

Я просто звонить в с PERL однострочника (избегая 'бесполезно использовать эхо'):

perl -lane 'print scalar(@F)' <<< $input 
Смежные вопросы