コンマ区切りのリストを次のコマンドの引数として指定する方法


9

s1「、」で区切られた数値のリストを出力するスクリプトがあります1,2,3,4。ここで、これらの数値をs2引数としてスクリプトに指定し、s2がそれぞれで実行され、その結果が別々の行に出力されるようにします。たとえば、s2が数値を2倍する場合、これは私が探している結果です。

2
4
6
8

私が今やっていることは:

s1 | xargs -d "," | xargs -n1 s2

でも馬鹿なやり方でやっているような気がします!だから私の質問は:

それを行う適切な方法は何ですか?

私の解決策の私の問題は、xargsを2回呼び出し、入力を2回反復することです。これはもちろん、パフォーマンスの観点から見ると妥当ではありません。答えxargs -d "," -n1はいいようですが、それが1回だけ繰り返されるかどうかはわかりません。もしそうなら、あなたの答えでそれを確認してください、そして私はそれを受け入れます。ちなみに、Perlはまだ2度繰り返されており、Perlが多くのシステムに存在しない可能性があるため、Perlは使用しません。


1
それが機能しているのなら、なぜそれを愚かと呼ぶのですか?実行時間が重要な場合、それは別の問題です
ジョージウドセン

2
これを試してくださいs1 | xargs -d "," -n1 s2
ジョージウドセン

1
問題のいくつかは反復の影響を誤解しているのではないかと思います。連想配列などの要素の繰り返し処理は、そのデータ構造をウォークする費用がかかるため不適切ですが、一般に「反復」は本質的に悪いことではありません。具体的には、STDINでデータを1行ずつ読み取ることは、大きなパフォーマンスの問題ではありません。ここでのパフォーマンスの問題は、新しいプロセスを生成し、パイプラインを設定するためのコストの増加です。(ループの場合のように)これを頻繁に行わない限り、xargsのパフォーマンスを心配することは、おそらく時期尚早の最適化の例です。
dannysauer 2017

回答:


18

これも同様に機能するはずです:

s1 | xargs -d "," -n1 s2

テストケース:

printf 1,2,3,4 | xargs -d ',' -n1 echo

結果:

1
2
3
4

場合はs1、リストには改行文字が続くことを出力そうでない場合は、最後の呼び出しはとなりますよう、あなたはそれを削除したいと思います4\n代わりに4

s1 | tr -d '\n' | xargs -d , -n1 s2

6

s2複数の引数を受け入れることができる場合は、次のようにすることができます。

(IFS=,; ./s2 $(./s1))

これは、IFSを一時的にオーバーライドして、すべてサブシェルでコンマにすることで、コンマs2s1分割された出力を確認します。サブシェルは、以前の値を保存したりリセットしたりせずにIFSを変更する簡単な方法です。

この回答の以前のバージョンは正しくありませんでした。おそらく残りのIFS設定が原因で、結果が破損しています。私の間違い指摘してくれたilkkachuに感謝します。

出力を手動でループして個別にに提供するにはs2、ここでIFSの保存とリセットを示します。

oIFS="$IFS"
IFS=,
for output in $(./s1); do ./s2 "$output"; done
IFS="$oIFS"

または、以前と同様にサブシェルでIFSビットを実行します。

(
IFS=,
for output in $(./s1); do ./s2 "$output"; done
)

1
最初のことでよろしいですか?私のシステムでbash -c 'IFS=, printf "%s\n" $(echo 1,2,3)'印刷1,2,3します。つまり、分割はありません。
ilkkachu 2017

少し後で再テストしますが、組み込みプログラムと外部プログラムに基づく動作の違いが疑われます。
ジェフシャラー

/usr/bin/printfおよびと同じ/bin/echo
ilkkachu 2017

1
@ilkkachu正解です。この場合(IFS=,; printf "%s\n" $(echo 1,2,3))、IFSが再割り当てされる前に単語分割が行われますが、これは機能するはずです。
アンダーキャットがモニカを称賛する

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.