Как перебирать слова моего текстового документа в оболочке. Я хочу отобразить количество слов в моем текстовом документе

Я пробовал это, но вместо этого он показывает количество строк.

declare -i x=0 while IFS = "" read -r p || [ -n "$p" ] do x=x+1 done <test.txt echo "$x

Буду признателен, если кто-нибудь сможет это объяснить, так как я новичок

wc -w test.txt?
tkausl 10.09.2018 08:39

Привет @tkausl. Это работает. Большое вам спасибо. Но я хочу повторить слова. Не только количество слов. заранее спасибо

Chitti_the_robot 10.09.2018 08:42

Пожалуйста, разместите несколько примеров данных с ожидаемым результатом, чтобы избежать неправильного понимания вопроса.

James Brown 10.09.2018 08:59
for i in $(cat file); do something $i; done вместо использования чтения и перенаправления, вероятно, является самым простым решением
Sam 10.09.2018 09:17

@Sam for i in $(cat file) - известный анти-паттерн. Всегда есть лучшее решение, чем это.

Ed Morton 11.09.2018 16:30

какое решение вы бы предпочли и почему тогда? Я прекрасно понимаю, что этот шаблон часто используется неправильно, но для меня это само по себе не означает, что его никогда не следует использовать.

Sam 11.09.2018 16:48

@Sam, если он содержит *, вы получите список повторяющихся имен файлов. Зачем вам вообще его использовать, если есть альтернативы, у которых нет побочных эффектов и ошибок? while read -r -a words; do for word in "${words[@]}"; do ...; done; done <test.txt

Charles Duffy 11.09.2018 17:54

у вас есть смысл в том, что с моей стороны было безрассудно предлагать без напоминания переключать глобус с помощью set -f / set +f, если есть малейшая вероятность, что файл может содержать какие-либо специальные символы.

Sam 11.09.2018 19:00

Однако обратите внимание, что set -f; for i in $(cat file); do echo $i >/dev/null; done; set +f примерно в два раза быстрее, чем эквивалентный while read -r -d' ' i; do echo $i >/dev/null; done для большого файла в моей системе, и что решение с массивом может дать сбой для очень длинных строк.

Sam 11.09.2018 19:10
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
9
65
3

Ответы 3

Предположим, что ваши слова разделены табуляцией, пробелами и символами новой строки, следующий фрагмент:

echo $'word1 word2! word3
\tword4\t\t\t\t\t\tword5\tword6
word7 word8


word9 word10' | \
while IFS=$'\t ' read -ra linewords; do
    for i in "${linewords[@]}"; do
            echo word is "'$i'"
    done
done

выведет:

word is 'word1'
word is 'word2!'
word is 'word3'
word is 'word4'
word is 'word5'
word is 'word6'
word is 'word7'
word is 'word8'
word is 'word9'
word is 'word10'

Он использует несколько значений IFS в сочетании с чтением read в массив, см. этот ответ о том, как разделить строку по разделителю.

Вы выбрали удобный вход, для которого работает ваш код :) Попробуйте использовать табуляцию между word5 и word6 вместо пробела. Проблема в том, что вы хотите использовать $'...' вместо $"...". См. руководство по эксплуатации для объяснения $"...". Кроме того, поскольку read по умолчанию считывает строки, в \n нет необходимости.

PesaThe 10.09.2018 11:24

Я бы использовал для этого awk:

$ echo "Lorem ipsum dolor sit amet,
        consectetur adipisci elit,
        ..." | 
awk '{
    for(i=1;i<=NF;i++)
        print "iterating " $i
}'

Выход:

iterating Lorem
iterating ipsum
iterating dolor
iterating sit
iterating amet,
iterating consectetur
iterating adipisci
iterating elit,
iterating ...
grep -oE '\w+' YOUR_FILE.txt

записывает слова из YOUR_FILE.txt в стандартный вывод. Вставьте это в свой цикл, и у вас будет итерация по словам.

Это предполагает, что «слово» в вашем случае - это один или несколько символов, описанных \w, то есть либо подчеркивание, либо то, что ваша текущая локаль определяет как буквенно-цифровой символ. Если ваше представление о «слове» отличается, вы, конечно, можете адаптировать регулярное выражение в соответствии со своими потребностями.

Другие вопросы по теме