1回の呼び出しで行を引数として使用する(xargsに似ています)

1回の呼び出しで行を引数として使用する(xargsに似ています)

いくつかの行を印刷する関数がありますが、それを別の関数の引数として使用したいと思います。

lsx() {
    echo 1 is one
    echo 2 are two
}

somefun() {
    for arg in "$@"; do
        echo "arg='$arg'"
    done
}

somefun()fromラインをlsx()パラメータとして使用して、「エレガントに」電話をかける方法は?

私が今やっていることは、ループを使って行を繰り返し、while行を配列に格納することです。しかし、これは見た目には良くなく、あまりにも効率的です。(編集:while + subshel​​lのため動作しません)。私は簡単な(または植え込み可能な)方法があるべきだと思いますが、それを理解することはできません。

somefun外部コマンドの場合は、次を使用します。パラメータしかしそれは真実ではない。 )

答え1

xargsなし

$ ( IFS=$'\n'; somefun $(lsx) )
arg='1 is one'
arg='2 are two'

IFSグローバル以外のローカル変更が行われるようにサブシェルが使用されます。

限定:これは出力がパス名拡張の影響を受け、lsxこれが問題になる可能性があります。

xargsによる

xargsを使用してシェル機能にアクセスするには、シェルを実行する必要があります。サブシェルにアクセスするには、somefunまずそれをエクスポートする必要があります。したがって:

$ export -f somefun
$ lsx | xargs -d'\n' bash -c 'somefun "$@"' SomeFun
arg='1 is one'
arg='2 are two'

最初の引数は、エラーメッセージのプログラム名bashに割り当てられて使用されます。$0どんな言葉でも可能です。ここではSomeFun

パス名拡張の問題の例

$ lsx() { echo '1 is one*'; echo '2 are two*'; }
$ touch '1 is one'{1..3} two{a..c}
$ ( IFS=$'\n'; somefun $(lsx) )
arg='1 is one1'
arg='1 is one2'
arg='1 is one3'
arg='2 are two*'

ご覧のとおり、出力の最初の行は3行に拡張されています。

シェルが最初に実行されました噴射出力に$(lsx)。 IFS が改行に設定されているため、出力は複数行に分割されます。その後、シェルが実行されます。パス名拡張。 globと一致するファイルがあるため、1 is one*globはこれらの名前のリストに展開されます。この例では、globと一致するファイルがないため、2 is two*globは拡張されません。 (デフォルトIFSでは2 is two*3つの単語に分割され、3番目の単語はfileとに一致しtwoaますtwobtwoc

このxargs方法はパス名の拡張を防ぎます。

$ export -f somefun
$ lsx | xargs -d'\n' bash -c 'somefun "$@"' SomeFun
arg='1 is one*'
arg='2 are two*'

答え2

簡単な解決策:

IFS="
"
somefun $(lsx)

関連情報