我很难打印一个数字序列,然后在末尾添加一些内容。
seq 1 3 | xargs -I {} echo {} 4
结果是
1 4
2 4
3 4
不过我希望结果是
1 2 3 4
由于我正在学习xargs
,我只想用它xargs
来实现这一目标。
答案1
如果您想将一定数量的行作为参数传递给command
via GNU的单次调用xargs
,您可以运行如下命令:
multi-line cmd | xargs -d '\n' -n N command
即用作\n
分隔符并一次传递第1N
行,这相当于运行command
command line1 line2 ... lineN
现在,xargs
操作如下:
input | xargs [options] [command [initial-arguments]]
这意味着在构建命令行时添加到命令行中的任何参数,它们都会出现在soxargs
的初始参数之后,例如command
multi-line cmd | xargs -d '\n' -n N command initial-args
将执行
command initial-args line1 line2 ... lineN
这就是为什么你无法运行
seq 1 3 | xargs -d '\n' -n 3 echo 4
并获得预期的输出,因为4
将被视为初始参数,最终结果将是
4 1 2 3
您可以做的是调用sh
ell 来运行command
- 这将使您能够在末尾放置任何其他参数:
seq 1 3 | xargs -d '\n' -n 3 sh -c 'echo "$@" 4' bang
1 2 3 4
bang
上面一行字里写的是什么?sh -c
句法是
sh -c command_string [command_name [argument...]]
所以 (扩展为位置参数,在本例中是由 ) 添加的参数,'echo "$@" 4'
并且是特殊参数,(您可以使用任何名称,例如) 值得一读:command_string
$@
xargs
bang
0
command_name
sh
为什么 $0 不是位置参数?
请注意,我的帖子涉及 GNUxargs
及其专有-d
开关。或者,您可以在 shell 中执行此操作,将输出行保存到数组中并将其元素作为参数传递到command
任何其他参数之前,
例如bash
readarray -t args < <(multi-line cmd)
command "${args[@]}" additional-arg(s)
或与zsh
args=("${(@f)$(multi-line cmd)}")
command "${args[@]}" additional-arg(s)
1:假设这些N
线在ARG_MAX
限制范围内
答案2
将一些行更改为单行是通过 完成的paste -s
。
在本例中,您希望将四行更改为一行。这四行是用以下命令创建的seq 1 3; echo 4
:
$ seq 1 3; echo 4
1
2
3
4
传递这些内容paste -d ' ' -s -
以将它们转换为一行,并用空格字符分隔每个原始行:
$ { seq 1 3; echo 4; } | paste -d ' ' -s -
1 2 3 4
tr '\n' ' '
您可以通过而不是通过来传递行paste -s
,但这也会用空格替换最后的换行符(后面的那个4
),这可能不是您想要做的。
答案3
xargs 部分很好。 seq 可以像这样使用分隔符
seq -s ' ' 1 3 | xargs -I {} echo {} 4
答案4
在 BSD 上,该选项的用途如下-J
:
$ seq 3 | xargs -J {} echo {} 4
1 2 3 4
无论如何,xargs
如果参数列表太大以至于超出限制,仍然会多次调用该命令execve()
。
对于其他xargs
实现,正如已经说过的,您可以sh
重新排序参数:
$ seq 3 | xargs sh -c 'echo "$@" 4' sh
1 2 3 4
对于xargs
不支持该-r
选项的实现,您还可以sh
检查是否至少传递了一个参数:
cmd1 | xargs sh -c '[ "$#" -eq 0 ] || exec cmd2 "$@" additional args' sh
请注意,exec
这会在 shell 实现中保存一个分叉,但不会自动执行该优化。对于诸如 之类的内置命令echo
,在某些sh
实现(例如 bash)中,使用exec
会导致外部的要调用的命令(如果可用)而不是内置命令,使其行为更像sh
未使用时 ( xargs cmd2
)。