Я пытаюсь запустить цикл for
для файла и хочу отобразить всю строку. Но вместо этого отображается только последнее слово. Я хочу полную линию.
for j in `cat ./file_wget_med`
do
echo $j
done
результат после запуска:
Found.
Вот мои данные:
$ cat file_wget_med
2013-09-11 14:27:03 ERROR 404: Not Found.
for
цикл разделяется, когда он видит любые пробелы, такие как пробел, табуляция или перевод строки. Итак, вы должны использовать IFS (Внутренний разделитель полей) :
IFS=\n' # make newlines the only separator
for j in $(cat ./file_wget_med)
do
echo "$j"
done
for
циклы разбиваются на любые пробелы (пробел, табуляция, новая строка) по умолчанию; Самый простой способ работать с одной строкой за раз - это использовать цикл while read
, который разделяется на новые строки:
while read i; do echo "$i"; done < ./file_wget_med
Я бы ожидал ваша команда выплевывать по одному слову в строке (это то, что произошло, когда я проверил это с моим собственным файлом). Если что-то еще происходит, я не уверен, что может быть причиной.
#!/bin/bash
files=`find <subdir> -name '*'`
while read -r fname; do
echo $fname
done <<< "$files"
Проверенная работа, не тот лайнер, который вы, вероятно, хотите, но это невозможно сделать элегантно.
Вот небольшое расширение ответа Митчелла Карри, которое мне нравится из-за небольшого количества побочных эффектов, которое позволяет избежать необходимости устанавливать переменную:
Я бы написал так:
cat ./file_wget_med | while read -r j
do
echo $j
done
, так как он требует наименьших изменений в исходном скрипте (за исключением решения с использованием IFS
, но оно изменяет поведение bash
не только для этого цикла). контрольное заявление).
Дэндальф очень близко подошел к функциональному решению, но НИКОГДА НЕ ДОЛЖНО пытаться присвоить результат неизвестных величин ввода (т. Е. find ~/.gdfuse -name '*'
) переменным! Или, по крайней мере, попытаться сделать это через переменную массива; если вы настаиваете на том, чтобы быть таким ленивым! Итак, вот решение Дэндальфа, выполненное без опасного маневра; и всего в одной строке
while read -r fname; do
echo $fname;
done <<< `find ~/.gdfuse -name '*'
Mapfile является удобным способом считать строки из файла в индексный массив, не столь портативный, как читает , но немного быстрее. При помощи для цикла Вы стараетесь не создавать подоболочку.
#!/bin/bash
mapfile -t < file.txt
for line in "${MAPFILE[@]}"; do
echo $line
done
Имеют в виду при использовании конвейеров, это поместит цикл с условием продолжения в подоболочку. Изменения в цикле с условием продолжения как переменные не распространят к внешней части сценария.
Пример:
#!/bin/bash
a=0
printf %s\\n {0..5} | while read; do
((a++))
done
echo $a # 'a' will always be 0.
(Лучшее решение):
#!/bin/bash
b=0
while read; do
((b++))
done < <(printf %s\\n {0..5})
echo $b # 'b' equal to 6 (works as expected).