xargsにリスト/配列をエコーし​​ます。

xargsにリスト/配列をエコーし​​ます。

リスト/配列があるとしましょう。

list=(a b c)

各要素をxargsにエコーする方法は?それは次のとおりです。

for v in list; do echo v; done; | xargs

もっと簡単な方法がありますか?

答え1

printf '%s\n' "${list[@]}" | xargs

これにより、list各要素が1行に印刷され、改行で区切られたリストがに渡されますxargs

"${list[@]}"に拡張される個々の二重引用符要素listprintf書式文字列のプレースホルダよりも多くの引数が指定された場合、その書式文字列は再利用されます。

ただし、要素には空白、一重引用符、二重引用符、またはバックスラッシュ文字が含まれておらず、空の文字列ではない場合にのみ機能します(一部のxargs実装はテキストのみで構成され、テキストではなく_比較的短い)。

任意の(長すぎない1)要素(NUL文字を含まないが、現在のバージョンのbashはとにかく変数にNULを格納できない)の場合、ほとんどの実装xargsでサポートされているNULで区切られたレコードオプションとしてリストを渡すことができます-0(Appearing POSIX規格の次のバージョンから):

{
  [ "${#list[@]}" -eq 0 ] || printf '%s\0' "${list[@]}"
} | xargs

print0ヘルパー機能を使用すると役に立ちます。

print0() {
  [ "$#" -eq 0 ] || printf '%s\0' "$@"
}
print0 "${list[@]}" | xargs -0

NetBSDを除く空のリストの場合、コマンドはecho(デフォルトでは)引数なしで一度だけ呼び出されます。このオプションを使用すると、この-r状況を回避できます(POSIX規格の次のバージョンでも同様)。


¹ システムコールの制限をxargs解決するように設計されていますが、execve()途中で個々の引数を削除しないため、単一の引数が制限より大きい場合、execve()コマンドは実行されません。さらに、Linuxには、ほとんどのシステムに共通のすべてのパラメータと環境変数の累積サイズに対する完全な制限とは異なり、個々のパラメータのサイズに対する制限があります。

答え2

特に長いリストでなければxargs完全にあきらめてもいいです。

list=(a b c)

# With xargs
printf "%s\n" "${list[@]}" | xargs foo    # Results in « foo a b c »

# Without xargs
foo "${list[@]}"                          # Also results in « foo a b c »

もちろん、これをあなたのケースに適用できるかどうかは、xargs実際のコマンドに渡したい追加のフラグが何であるかによって異なります。

これをテストするには、fooこのスクリプトを実行して上記のすべてのインスタンスをfoo次のように置き換えます./foo

cat <<'EOF' > foo
#!/bin/bash
echo "Got $# arg(s): $*"
for ARG in "$@"; do echo "> $ARG <"; done
EOF
chmod a+x foo

また、デフォルトでは(ここに示すように)その引数xargsはスペースに分割されているため、次のようになります。

list=('a b' c d)                          # Three arguments; the first contains a space
printf "%s\n" "${list[@]}" | xargs foo    # Gives foo four arguments « a b c d »
foo "${list[@]}"                          # Gives foo three arguments, with the first containing a space, « 'a b' c d »

関連情報