Я пробовал это, но вместо этого он показывает количество строк.
declare -i x=0 while IFS = "" read -r p || [ -n "$p" ] do x=x+1 done <test.txt echo "$x
Буду признателен, если кто-нибудь сможет это объяснить, так как я новичок
Привет @tkausl. Это работает. Большое вам спасибо. Но я хочу повторить слова. Не только количество слов. заранее спасибо
Пожалуйста, разместите несколько примеров данных с ожидаемым результатом, чтобы избежать неправильного понимания вопроса.
for i in $(cat file); do something $i; done
вместо использования чтения и перенаправления, вероятно, является самым простым решением
@Sam for i in $(cat file)
- известный анти-паттерн. Всегда есть лучшее решение, чем это.
какое решение вы бы предпочли и почему тогда? Я прекрасно понимаю, что этот шаблон часто используется неправильно, но для меня это само по себе не означает, что его никогда не следует использовать.
@Sam, если он содержит *
, вы получите список повторяющихся имен файлов. Зачем вам вообще его использовать, если есть альтернативы, у которых нет побочных эффектов и ошибок? while read -r -a words; do for word in "${words[@]}"; do ...; done; done <test.txt
у вас есть смысл в том, что с моей стороны было безрассудно предлагать без напоминания переключать глобус с помощью set -f
/ set +f
, если есть малейшая вероятность, что файл может содержать какие-либо специальные символы.
Однако обратите внимание, что 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
для большого файла в моей системе, и что решение с массивом может дать сбой для очень длинных строк.
Предположим, что ваши слова разделены табуляцией, пробелами и символами новой строки, следующий фрагмент:
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
нет необходимости.
Я бы использовал для этого 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
, то есть либо подчеркивание, либо то, что ваша текущая локаль определяет как буквенно-цифровой символ. Если ваше представление о «слове» отличается, вы, конечно, можете адаптировать регулярное выражение в соответствии со своими потребностями.
wc -w test.txt
?