これが私の問題です
$ 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
これは私が期待することですが、
$ 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
出力はすべきではありませんか?
arg: ac s
arg: bc s
arg: cc s
DONE
Xargsで2番目の出力を取得するにはどうすればよいですか?
試してください:
printf %b 'ac s\nbc s\ncc s\n' | xargs -d '\n' bash /tmp/test.sh
\n
に渡された-d
の引用を怠ったため、\n
ではなくn
が区切り文字としてxargs
に渡された-シェルは「ate」 \
(シェルが引用符で囲まれていない文字列を解析する場合、\
はエスケープ文字として機能します。通常の文字が\
-この場合はn
に続く場合、その通常の文字のみが使用されます) 。
また、スクリプト内で$@
を二重引用符で囲む(またはin "$@"
の部分を完全に省略する)ことは、@ glennジャックマンのアドバイスにも注意してください。
また:xargs -d
はGNU拡張であり、たとえば、FreeBSD/macOSでは機能しません。そこで機能させるには、@を参照してください。 glenn jackmanのxargs -0
ベースのソリューション。
文字列の\n
インスタンスがallBourne-likeの改行として解釈されるようにするために、printf
ではなくecho
を使用していることに注意してくださいシェル:bash
およびksh
[1]、echo
のデフォルトは、\
ベースのエスケープシーケンスを解釈しない(これを実現するには-e
を使用する必要があります)-zsh
やdash
などのPOSIXに厳密に準拠したシェルとは異なります。
したがって、printf
の方が移植性が高くなります。
[1]マニュアルによると、ksh
のecho
builtinは、ホストプラットフォームの外部echo
utility;これはプラットフォームによって異なる可能性がありますが、LinuxおよびBSD/macOSの実装では、デフォルトで\
エスケープシーケンスを解釈しません。
シェルスクリプトは"$@"
ではなく$@
を使用する必要があります
http://www.gnu.org/software/bash/manual/bashref.html#Special-Parameters を参照してください
私のマシンのxargsマニュアルで私は見ます:
xargsは、blanks [...]または改行で区切られた標準入力から項目を読み取ります
(強調鉱山)
したがって:
$ 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
前者を使用すると、以下と同等になります。
bash /tmp/test.sh ac s bc s cc s
null-separatorの使用との比較
bash /tmp/test.sh "ac s" "bc s" "cc s"
データに空白が含まれている場合は、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
最後の場合の追加の引数に注意してください。echo
はすでに改行を追加しているため、echo -n
を使用しない限り、追加の引数は必要ありません。