将文件行读入 shell 中,每行以空格分隔

将文件行读入 shell 中,每行以空格分隔

我有一个名为 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 – 对于软件包安装,这可能是明智的。?-mmxargsparallel-j11 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_testfilefile的内容包含两行:a*b with spaces。 本例中的第三行命令行printf "line: %s\n"以来自的所有行file作为其参数执行,这会打印参数,其前带有“line: ”,后带有换行符。 由于没有通配符,第一个参数a*无法匹配现有文件a_test,但会按原样打印。 下一个带有空格的参数也是如此,空格被保留,而不是将参数分成三个。

第四条命令仅仅是一个附录,展示了 的众多优秀特性之一parallel{#}命令中的 被作业的序列号所取代,并且由于该命令printf仅使用一个参数(没有-m)调用,因此它等于当前行号。{}是参数的占位符,如果命令中没有使用其他占位符并且可以省略,并且应该将参数添加到命令的末尾,就像我之前所做的那样。

关于 GNU 的更多阅读parallel

相关内容