我有一个名为 requirements.txt 的文件,每行都有一个包:
package1
package2
package3
我正在寻找一个命令,它将把 requirements.txt 的每一行合并到一行中,并以空格分隔。
所以基本上,我希望生成以下命令:
command package1 package2 package3
我尝试使用 for 并应用command
每一行requirements.txt
,但是速度慢得多
答案1
您可以使用xargs
,并将分隔符设置为换行符(\n
):这将确保即使参数包含空格也能正确传递:
xargs -rd'\n' command < requirements.txt
从手册页:
-r
,--no-run-if-empty
如果标准输入不包含任何非空白,则不运行该命令。通常,即使没有输入,该命令也会运行一次。此选项是 GNU 扩展。
--delimiter=delim
,-d delim
输入项以指定字符终止。
答案2
您可以简单地使用bash
重定向和命令替换来将文件内容作为命令的参数:
command $(<file)
这是可行的,因为不仅空格是有效的分词字符,换行符也是有效的——你不需要替换任何东西。然而,在许多行,您将得到一个错误,指出 shell 的ARG_MAX
限制(就像您使用替代解决方案时一样)。使用printf
构建一个参数列表,并xargs
从中构建命令行来解决这个问题:
printf "%s\0" $(<file) | xargs -0 command
请注意,这两种方法都不适用于包含空格或通配符的行(当然除了换行符)——幸运的是,包名称不适用(据我所知)。如果行中有空格或通配符,请使用其中一种xargs
(请参阅这个答案)或parallel
(见这个答案)。
答案3
使用tr
和 bash 替换:
command $(tr '\n' ' ' < requirements.txt)
例如:
echo $(tr '\n' ' ' < requirements.txt)
输出为:
package1 package2 package3
或者:
sudo apt install -y $(tr '\n' ' ' < requirements.txt)
将安装所有软件包。
答案4
您可以使用GNUparallel
为了这 (sudo apt install parallel
):
parallel -m command <file # or
parallel -m command :::: file
parallel
仅使用换行符作为分隔符,并且(当然)不执行任何通配符,因此行中的空格、星号*
、问号等字符完全没有问题。用于多个参数,就像这样做一样。如果您不希望命令行并行运行(默认情况下是并行运行的),请一次添加for ob – 对于软件包安装,这可能是明智的。?
-m
m
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
作为其参数执行,这会打印参数,其前带有“line: ”,后带有换行符。 由于没有通配符,第一个参数a*
无法匹配现有文件a_test
,但会按原样打印。 下一个带有空格的参数也是如此,空格被保留,而不是将参数分成三个。
第四条命令仅仅是一个附录,展示了 的众多优秀特性之一parallel
:{#}
命令中的 被作业的序列号所取代,并且由于该命令printf
仅使用一个参数(没有-m
)调用,因此它等于当前行号。{}
是参数的占位符,如果命令中没有使用其他占位符并且可以省略,并且应该将参数添加到命令的末尾,就像我之前所做的那样。