Считать строки файла в строку оболочки, разделенную пробелом

У меня есть файл под названием needs.txt, в каждой строке есть пакет:

package1
package2
package3

Я ищу команду, которая возьмет каждую строку в файле require.txt и объединит их в одну строку, разделенное пробелом.

Итак, в основном, я пытаюсь сгенерировать следующую команду:

command package1 package2 package3

Я пытался использовать for и применять command для каждой строки requirements.txt, но это было намного медленнее

7
задан 24 August 2019 в 00:37

6 ответов

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

command $(<file)

Это работает, потому что не только располагают с интервалами, допустимый символ разделения слова, но и новая строка также – Вы ничем не должны заменять. Однако в случае многих строк Вы получите ошибку при обращении к оболочке ARG_MAX предел (поскольку Вы будете с решениями для замены). Использовать printf к созданному список аргументов и xargs к созданным командным строкам от него для работы вокруг этого:

printf "%s\0" $(<file) | xargs -0 command

Обратите внимание, что ни один из этих подходов работа для строк, содержащих пробел или globbing символы (помимо новой строки, конечно) – к счастью, имена пакета, не делает (AFAIK). Если у Вас есть пробел, или globbing символы в строках используют также xargs (см. этот ответ), или parallel (см. этот ответ).

7
ответ дан 23 November 2019 в 06:09

Можно использовать xargs, с набором разделителя к новой строке (\n): это гарантирует, что аргументы передаются правильно, даже если они содержат пробел:

xargs -rd'\n' command < requirements.txt
11
ответ дан 23 November 2019 в 06:09

Использовать tr и замена удара:

command $(tr '\n' ' ' < requirements.txt)

например:

echo $(tr '\n' ' ' < requirements.txt)

вывод был бы:

package1 package2 package3

или:

sudo apt install -y $(tr '\n' ' ' < requirements.txt)

установил бы все пакеты.

3
ответ дан 23 November 2019 в 06:09

Считайте объекты из файла вместо стандартного входа:

xargs --arg-file=requirements.txt echo

Или, чтобы перестать работать, если список аргументов является слишком длинным (вместо выполнения echo несколько раз):

xargs --arg-file=requirements.txt -n 1 echo

Краткая форма для --arg-file -a, таким образом, можно использовать xargs -a requirements.txt вместо --arg-file=requirements.txt если Вы хотите.

2
ответ дан 23 November 2019 в 06:09

Можно использовать GNU parallel для этого (sudo apt install parallel):

parallel -m command <file     # or
parallel -m command :::: file

parallel берет только новую строку в качестве символа-разделителя и (конечно) не выполняет globbing, так символы как пространство, звездочка*, вопросительный знак ? и т.п. в строках не проблема вообще. -m для mаргументы ultiple как xargs он. Если Вы не хотите, чтобы командные строки были выполнены параллельно, который является что parallel делает по умолчанию, добавляют -j1 для 1 jОбь за один раз – для установки пакета это может быть желательно.

Пример выполняется

$ ls
a_test  file
$ cat file
a*
b with spaces
$ parallel -m 'printf "line: %s\n"' <file
line: a*
line: b with spaces
$ parallel 'printf "line {#}: %s\n" {}' <file
line 1: a*
line 2: b with spaces

Каталог содержит два файла: a_test и file. fileсодержание состоит из двух строк: a* и b with spaces. Третья командная строка в этом примере выполняется printf "line: %s\n" со всеми строками от file как его аргументы, это печатает спор со “строкой”: прежде и разрыв строки после него. Как нет никакого globbing, первого аргумента a* не может соответствовать существующему файлу a_test, но печатается как есть. То же идет для следующего спора с пробелами в нем, пробелы сохраняются вместо аргумента, разделяемого на три.

Четвертая команда является просто приложением, показывающим одну из многих хороших функций parallel: {#} в команде заменяется порядковым номером задания, и как эти вызовы printf только с одним аргументом (нет -m) это равно текущему номеру строки. {} заполнитель для аргумента (аргументов) и может быть опущен, если нет никакого другого заполнителя, используемого в команде, и аргумент (аргументы) должен быть добавлен в конец команды, которую я сделал прежде.

Дополнительные материалы для чтения на GNU parallel:

1
ответ дан 23 November 2019 в 06:09

Просто прочитайте строки в массив. Это легко сделать с помощью 4 (который предоставляет команду readarray):

readarray -t lines < /path/to/file
echo "${lines[@]}"
1
ответ дан 9 September 2020 в 00:13

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

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