这是我的问题
$ echo 'for i in $@; do echo arg: $i; done; echo DONE' > /tmp/test.sh
$ echo "ac\nbc\ncc\n" | xargs bash /tmp/test.sh 
arg: ac
arg: bc
arg: cc
DONE
Run Code Online (Sandbox Code Playgroud)
这是我所期待的,但是
$ echo "ac s\nbc s\ncc s\n" | xargs -d \n bash /tmp/test.sh
arg: ac
arg: s
arg: bc
arg: s
arg: cc
arg: s
DONE
Run Code Online (Sandbox Code Playgroud)
输出不应该是?
arg: ac s
arg: bc s
arg: cc s
DONE
Run Code Online (Sandbox Code Playgroud)
如何使用xargs获得第二个输出?
mkl*_*nt0 16
尝试:
printf %b 'ac s\nbc s\ncc s\n' | xargs -d '\n' bash /tmp/test.sh
Run Code Online (Sandbox Code Playgroud)
你忽略了引用\n传递给-d,这意味着刚刚n而非\n传递给xargs作为分隔符-壳"吃"了\(当壳解析一个不带引号的字符串,   \用作转义字符;如果一个普通字符如下\- n中这种情况 - 只使用普通字符).
另请注意@glenn jackman建议$@在脚本内部加双引号(或in "$@"完全省略该部分).
另外:xargs -d是一个GNU扩展,例如,它不适用于FreeBSD/macOS.要使它在那里工作,请参阅@glenn jackman的xargs -0解决方案.
请注意,我正在使用printf而不是echo确保\n字符串中的实例在所有类似Bourne的shell中被解释为换行符:
在bash和ksh[1]中,echo默认为NOT解释\基于转义的转义序列(您必须使用它-e来实现) - 不像在zsh和严格的POSIX兼容的外壳,如dash.
因此,printf是更便携的选择.
[1]根据本说明书,ksh的echo 内置表现出相同的行为,主机平台的外部echo 效用 ; 虽然这可能因平台而异,但Linux和BSD/macOS实现默认不解释\转义序列.
cmc*_*nty 13
对于具有已知数量 args 的简单情况,告诉 xargs 向每个命令发送多少个 args。例如
$ echo "1\n2\n3" | xargs -n1 echo "#"
# 1
# 2
# 3
Run Code Online (Sandbox Code Playgroud)
当您的输入参数很复杂并且换行符终止时,更好的方法是:
$ echo "1\n2 3\n4 5 6" | xargs -L1 echo  "#"
# 1
# 2 3
# 4 5 6
Run Code Online (Sandbox Code Playgroud)
这里有一个探测器,你能看到吗?如果我们的输入行包含单引号怎么办:
$ echo "1\n2 3\n4 '5 6" | xargs -L1 echo  "#"
# 1
# 2 3
xargs: unterminated quote
Run Code Online (Sandbox Code Playgroud)
xargs不喜欢单引号,除非你使用-0flag。但是-0和-L1不兼容,所以我们有:
$ echo "1\n2 3\n4 '5 6" | tr '\n' '\0' | xargs -0 -I{} echo "#" {}
# 1
# 2 3
# 4 '5 6
Run Code Online (Sandbox Code Playgroud)
如果你brew install findutils能做得更好一点:
$ echo "1\n2 3\n4 '5 6" | gxargs -d\\n -i echo "#" {}
# 1
# 2 3
# 4 '5 6
Run Code Online (Sandbox Code Playgroud)
但是等等,也许 usingxargs只是这个工具的一个坏工具。如果我们改用 shell 内置函数会怎样:
$ echo "1\n2 3\n4 '5 6" | while read -r; do echo "# $REPLY"; done
# 1
# 2 3
# 4 '5 6
Run Code Online (Sandbox Code Playgroud)
有关xargsvswhile结帐的更多想法,请查看此问题。
你的shell脚本需要使用"$@"不$@
请参阅http://www.gnu.org/software/bash/manual/bashref.html#Special-Parameters
我在机器上的xargs手册中看到:
xargs从标准输入中读取项目,由空格[...]或换行符分隔
(强调我的)
从而:
$ echo $'ac s\nbc s\ncc s\n' | xargs bash /tmp/test.sh  
arg: ac
arg: s
arg: bc
arg: s
arg: cc
arg: s
DONE
$ printf "%s\0" "ac s" "bc s" "cc s" | xargs -0 bash /tmp/test.sh
arg: ac s
arg: bc s
arg: cc s
DONE
Run Code Online (Sandbox Code Playgroud)
对于前者,你得到的相当于
bash /tmp/test.sh ac s bc s cc s
Run Code Online (Sandbox Code Playgroud)
与使用空分隔符
bash /tmp/test.sh "ac s" "bc s" "cc s"
Run Code Online (Sandbox Code Playgroud)
当数据包含空格时,您需要清楚分隔符与xargs的对应关系.
$ printf "%s\n" "ac s" "bc s" "cc s" | xargs -d $'\n' bash /tmp/test.sh
arg: ac s
arg: bc s
arg: cc s
DONE
$ echo $'ac s\nbc s\ncc s\n' | xargs -d $'\n' bash /tmp/test.sh  
arg: ac s
arg: bc s
arg: cc s
arg:  
DONE
Run Code Online (Sandbox Code Playgroud)
请注意,在最后一种情况下,额外的arg echo已添加换行符,因此除非您使用,否则不需要额外的换行符echo -n