web-dev-qa-db-ja.com

xargs --max-args--replaceをデフォルトの区切り文字で使用する際の問題

これは期待どおりに機能します。

$ echo a b c | xargs --replace="{}" echo x "{}" y
x a b c y

これもそうです:

$ echo a b c | xargs --max-args=1 echo x
x a
x b
x c

しかし、これは期待どおりに機能しません。

$ echo a b c | xargs --max-args=1 --replace="{}" echo x "{}" y
x a b c y

そしてこれも行いません:

$ echo a b c | xargs --delimiter=' ' --max-args=1 --replace="{}" echo x "{}" y
x a y
x b y
x c
 y

私はこの出力を期待していました:

x a y
x b y
x c y

回避策として、printfと2つのxargsを使用していますが、これは醜いです。

$ echo a b c | xargs printf '%s\0' | \
> xargs --null --max-args=1 --replace="{}" echo x "{}" y
x a y
x b y
x c y

なぜこれが起こっているのでしょうか?

6
Pedro Gimeno

POSIXドキュメント によると、xargsは指定されたユーティリティをスペースまたは改行で区切られた引数で実行する必要があります。これが最初の2つの例で発生するものです。

ただし、--replace(または-I)が使用されている場合、引数を区切るのは改行だけです。解決策は、xargs引数を別々の行に指定することです。

$ printf '%s\n' a b c | xargs --max-args=1 --replace="{}" echo x "{}" y
x a y
x b y
x c y

POSIXオプションの使用:

printf '%s\n' a b c | xargs -n 1 -I "{}" echo x "{}" y

ここでは、xargsを1行ではなく3行示します。 (最大で)1行かかり、それを引数としてユーティリティを実行します。

上記の-n 1(または--max-args=1)は、使用される引数の数を決定するのは-Iによって行われた置換の数であるため、必要ないことにも注意してください。

$ printf '%s\n' a b c | xargs -I "{}" echo x "{}" y
x a y
x b y
x c y

実際、xargsに関するPOSIX仕様の理論的根拠のセクションには(私の強調)と書かれています。

-I-L、および-nオプションは相互に排他的です。一部の実装では、コマンドラインで複数指定された場合に指定された最後のものを使用します。他の実装では、オプションの組み合わせをさまざまな方法で扱います。

これをテストしているときに、OpenBSDのバージョンのxargsは、-n-Iを一緒に使用すると、次のようになることに気付きました。

$ echo  a b c | xargs -n 1  -I "{}" echo x "{}" y
x a y
x b y
x c y

これは、GNU coreutils'xargsが行うこと(x a b c yを生成します)とは異なります。これは、-nが使用されている場合でも、実装が-Iで引数区切り文字としてスペースを受け入れるためです。したがって、-I-nを一緒に使用しないでください(いずれにしても必要ありません)。

5
Kusalananda

私が見つけた回避策の1つは、-max-argsの出力を次のように--replaceにフィードすることでした。

echo a b c | xargs -n 1 | xargs -i echo firstPart {} secondPart

これが出力されます。

firstPart a secondPart
firstPart b secondPart
firstPart b secondPart

基本的には--max-argsを使用して入力をループし、デフォルトで改行文字を追加していると思います。

0
Meister182