Как зациклить переменную в виде строки, а не слова из текста?

Это ВХОД:

$ ls -1  # list folder name in current folder.
the cat
the dog
the rat

$ for var in $(ls -1); do echo $var; done # the command

Это ВЫХОД, что он сделал:

the
cat
the 
dog
the 
rat

Это ВЫХОД, который мне нужен:

the cat
the dog
the rat
1
задан 21 August 2019 в 11:08

4 ответа

В случае, если Вы используете ls только как пример для иллюстрирования вывода, который может содержать пробелы можно попробовать это (замена ls с Вашей командой):

ls | while IFS= read -r line ; do
   echo "$line"
done

Без IFS=, read управляйте пробелом полос вначале и концом каждой строки. Без -r, это рассматривает \ в конце строки входа как символ продолжения строки, и просто удаляет другой \ персонажи.

Отметьте это ls самостоятельно значения по умолчанию в один файл на строку при передаче по каналу, даже когда Вы не передаете -1. (Возможно иметь больше чем одну строку на файл, тем не менее, потому что именам файлов разрешают содержать символы новой строки.)   При передаче по каналу, ls также отключает цвет, если обычно включено.

Для обработки файла можно попробовать:

while IFS= read -r line ; do
   echo "$line"
done < file.txt

Если Вы хотите циклично выполниться по именам файлов, bash имеет встроенную возможность, без парсинга ls:

for file in * ; do
   echo "$file"
done
3
ответ дан 3 December 2019 в 06:49

Вместо записи $(ls -1), просто запишите *. Это - шарик.

Отдельно, * расширяется до списка файлов (регулярные файлы, каталоги, и т.д.) в текущем каталоге. По умолчанию, файлы, имена которых запускаются с . опущены, который является также поведением ls и то, что Вы обычно хотите.

$ for f in *; do echo "$f"; done
the cat
the dog
the rat

Globbing также называют расширением имени файла или расширением пути.

В целом, лучше стараться не анализировать вывод ls. Попытки сделать так являются почти всегда неправильными и обычно довольно сложными. Когда Ваша цель состоит в том, чтобы извлечь и использовать имена файлов в качестве аргументов команде, в качестве в вопросе, который задают здесь, это не просто трудно, но и на практике невозможно записать корректное ls- парсинг решения. ls команда производит вывод, предназначенный, чтобы быть считанной человеком. Имена файлов могут содержать любой символ кроме / и нулевой символ, даже новые строки. Кроме того, наиболее распространенные способы люди пытаются проанализировать вывод ls повреждение на чрезвычайно общих именах файлов, как любое имя файла, которое имеет пространство в нем. В этом случае различие в сложности является абсолютным: все, в чем Вы нуждаетесь, *.

Другая большая вещь быть осторожным относительно здесь заключает в кавычки. Когда Вы пишете цикл оболочки (который это само часто лучше всего избегаемый), расширения переменной цикла-$f в этом примере - должен почти всегда включаться в двойные кавычки, как показано выше. Иначе оболочка пытается выполнить разделение слова и (в этом случае, дополнительный и нежелательный) globbing. Если Вы не можете ясно объяснить, почему Вы не находитесь в одном из редких сценариев, где переменное расширение должно закрыться кавычки, необходимо заключить его в кавычки.

Наконец, обратите внимание, что много команд рассматривают аргументы особенно в некоторых или всех положениях, когда аргументы запускаются с -. Главная причина для этого состоит в том, что большинство команд принимает опции, представленные -, как -l (хотя некоторые команды также берут - отдельно означать stdin или stdout). Но для имен файлов возможно запуститься с -. Многие, хотя не все, команды принимают -- указать на конец опций, так, чтобы последующие аргументы были интерпретированы как имена файлов, даже если они запустят с -. Еще более широко применимое решение состоит в том, чтобы гарантировать, что файлы указаны с путями, которые не запускаются с -, например, путем расширения шарика ./* вместо *. Что касается echo, это не рассматривает -- особенно, и выводу, Вы сказали Вас, было нужно, не имеет запаздывания ./; быть устойчивым перед лицом имени файла, которые запускаются с - (как -n, который говорит echo подавить заключительную новую строку), можно заменить echo с printf '%s\n'.

Хотя * был упомянут в другом месте на этой странице, я думаю, что она заслуживает своего собственного ответа. Globbing (с *) единственное разумное решение фактической задачи этот вопрос подарки. Это не альтернатива использованию ls с заменой команды или передачей по каналу вывода ls кому: while- потому что те методы просто не делают правильной вещи и никогда не должны использоваться. Просто не выполнимо заставить те другие подходы работать правильно с ls.

1
ответ дан 3 December 2019 в 06:49

Необходимо сначала установить IFS (Внутренний Разделитель полей) к новой строке, затем

IFS=$'\n' && for var in $(ls -1); do echo $var; done

будет работать

0
ответ дан 3 December 2019 в 06:49

Можно использовать mapfile для чтения строк из стандартного входа в индексный массив:

mapfile -t < <(ls -1); for i in "${MAPFILE[@]}"; do echo $i; done

0
ответ дан 3 December 2019 в 06:49

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

Похожие вопросы: