$()を使用して保存せずにコマンド出力を引数として実行するには?

$()を使用して保存せずにコマンド出力を引数として実行するには?

これは実際にbrew search

しかし、単純化のために次のようにすると仮定します。

echo -e 'somedir\n\otherdir'
somedir
otherdir

otherdirこれを行わずにパラメータとして使用できますか?

ls $(echo -e 'somedir\n\otherdir |tail -n1)
otherdir

目標を明確にするために更新されました

より明確にしてsomedirstdoutotherdirに行くには、単に行うことができます。otherdir

出力をキャプチャして $()からコマンドを実行しませんか?

私はこれが可能だと思いますが、それが可能だとは思わないかと思います。

答え1

以下を使用して、いつでもxargs出力ストリームをパラメータリストに変換できます。

printf 'somedir\n\otherdir\n' |
  tail -n1 |
  xargs -rd '\n' ls -l --

-d '\n'行にGNU実装が必要なので、ここでは引数が必要ですxargs

最後の行にスペース、引用符、バックスラッシュがない場合は省略できます。

-rls入力が空であれば実行を避ける必要がある、やはりGNUから来ましたがxargs現在は広くサポートされています(そしてPOSIX標準の次のバージョンに現れる予定です)。


コマンド置換を無効にするには、bashいつでもコマンド出力行を配列に読み込み、配列の最後の要素からコマンドを実行できます。

readarray -t lines < <(printf 'somedir\notherdir\n')
if (( ${#lines[@]} > 0 )); then
  ls -l -- "${line[@]: -1}"
fi

または以下を使用してくださいperl

printf 'somedir\notherdir\n' |
  perl -lne 'exec qw(ls -l --), $_ if eof && $.'

コマンド置換を使用すると、すべての末尾の改行が削除されるため、空の入力と空の最後の行を直接区別することはできません。どちらの場合も、拡張を取得して空になります。

コマンドの代替使用の利点の1つは、出力の使用を決定する前にコマンドが成功した(終了状態に基づいて)確認できることです。

die() { [ "$#" -eq 0 ] || printf>&2 '%s\n' "$@"; exit 1; }

last_line=$(
  set -o pipefail
  cmd | tail -n 1
) || die "cmd failed"

ls -l -- "$last_line"

あるいは、grepそれを使用して出力が空でないことを確認することもできます。

if
  last_line=$(
    set -o pipefail
    cmd |
      tail -n 1 |
      grep '^'
  )
then
  ls -l -- "$last_line"
else
  echo>&2 "Either cmd failed or it didn't produce any output"
fi

grep '^'行の先頭に一致します。したがって、出力に1つ以上の行が含まれている場合(空であるかどうかにかかわらず)、trueを返します。ただし、入力が改行で終わらないと、POSIX行の定義によって行と見なされず、grepこの場合、一部の実装が失敗したり、区切られていない行を削除したりする可能性があります。

答え2

文法$()番号救う何もない。これは基本的に「このコマンドを実行し、出力を引数として使用する」という意味です。

あなたの使い方は正しい標準的な作業方法です。

(まだ機能している)以前のシェルでは、バックティック( `)は次のように動作します。

しかし、これは$()現代的な方法であり、既存の方法が持っていたトリッキーな参照問題も多く解決します。

たとえば、ほぼどこでも使用できます。

echo "The current time is: $(date)"
The current time is: Tue Nov 21 22:57:41 EST 2023

関連情報