1. 概要

コマンドを使用する場合、あるコマンドの出力を別のコマンドに渡したい場合があります。 これは、パイプを使用して最も一般的に実現されますが、スクリプトを作成するときは、出力を変数に格納して処理できるようにすることをお勧めします。

このチュートリアルでは、コマンドの出力を変数に取り込む方法を見ていきます。 これをアドホックベースで実行する方法と、以前のコマンドの出力を簡単に参照できるようにするための、より長持ちするソリューションを作成する方法について説明します。

2. ユースケース

まず、出力のサイズが異なるいくつかのコマンドを見てみましょう。 wc コマンドは、スカラー値であるファイル内の単語数を出力します。 ls コマンドは値のリストを出力し、それをmvで使用してファイルをどこかに移動したい場合があります。

提示されたソリューションは両方のユースケースと互換性がありますが、単一の値またはリストを格納することの違いは、結果の変数の使用方法にあります。

2.1. ファイルのワード数に基づいてディレクトリを変更する

最初の使用例では、 wc-wコマンドの出力を保存します。

$ wc -w < file_with_5_words
5

この場合、ファイルfile_with_5_wordsには5つの単語があります。

その出力に対応する名前のディレクトリに変更したいとします。

$ cd 5

2.2. フォルダの内容に基づいて特定のファイルを移動する

2番目の使用例は、ファイルのリスト(拡張子が txt のファイル)をディレクトリに移動することです。 そのためには、最初にファイルをリストする必要があります。

$ ls *.txt
ax.txt ay.txt

mvコマンドの構文は次のとおりです。

mv file1 file2 ... targetDir

これは、コマンドが同時に複数のファイルを入力として受け入れることを意味します。

3. アドホックソリューション

これらのソリューションでは、関数や追加のファイルを作成する必要はありません。 たまに使用するのに理想的です。

デフォルトでは、シェルはコマンドの出力に関する情報を保存しません。 最後のコマンドの終了コードを参照することができます。 history コマンドを実行して、各操作のコマンドラインを確認することもできます。 したがって、出力をキャプチャするために特定の方法でコマンドを実行する必要があります。

3.1. 変数を明示的に使用する

コマンドのstdoutへの出力を含む変数を割り当てることができます。

$ var=$(wc -w < file_with_5_words)

これは、逆引用符を使用して実現することもできます。

$ var=`wc -w < file_with_5_words`

旧式の後方引用符置換は、 $ 、\、または実際の`自体のような特殊文字の意味を保持しません。 これらの文字は、円記号でエスケープする必要があります。 構文$(…)は、特別な方法で文字を処理しません。

これらのアプローチの両方で、 wc-wの出力をvarという名前の変数に格納しています。 次に、コマンドでドル記号の前にドル記号を付けることで、変数を使用できます。

$ cd $var

2番目のユースケースのソリューションも同様ですが、変数に複数の値が含まれている点が異なります。 echoコマンドで確認してみましょう。

$ var=`ls *.txt`
$ echo $var
ax.txt ay.txt

echo で変数の内容を確認し、2つのファイルがあることを確認した後。 mvで使用してみましょう。

$ mv $var 5

3.2. 変数を誤って使用した場合はどうなりますか?

シェル変数にはタイプがありません。 すべての変数が文字列であるかのように動作する必要があります。 したがって、変数の内容を受け入れることができるコマンドでのみ変数の内容を使用するように注意する必要があります。

たとえば、 ls (リスト)からの出力をcdコマンドで使用するとどうなるか見てみましょう。

$ var=$(ls *.txt)
$ echo $var
ax.txt ay.txt
$ cd $var
-bash: cd: too many arguments

ここで、 cd コマンドは、スペースで区切られた複数の値ではなく、1つの入力値のみを受け入れるため、失敗しました。

3.3. 履歴拡張の使用– !!

シェルはコマンドの出力を追跡しませんが、履歴展開を使用して前のコマンドを再実行し、その出力を変数に割り当てることができます。

$ ls *.txt
ax.txt ay.txt
$ var=$(!!)
var=$(ls *.txt)
$ echo $var
ax.txt ay.txt

同様に、 history の出力からの数値を使用して、以前のコマンドを再実行できます。

$ history
 1097  git log
 1098  ls *.txt
$ var=$(!1098)

このアプローチでは望ましくない結果が生じる可能性があることに注意してください。 たとえば、コマンドの出力が呼び出しごとに変わる場合、変数には最新の呼び出しの出力が含まれます。

4. 長期的なソリューション

コマンド出力を大量にキャプチャしている場合は、システムにスクリプトを設定して支援することをお勧めします。

4.1. Bash関数の使用

コマンド出力をキャプチャしてvarに配置する関数、out2varを定義しましょう。

out2var() {
  var=$("$@")
  printf '%s\n'$var
}

これにより、コマンドラインが入力パラメーター @ を介して実行され、出力がvarに格納されます。 出力を見たいので、printf呼び出しがあります。

関数out2varが呼び出されるたびに、変数varが割り当てられます。

$ out2var wc -w < file_with_5_words
5
$ echo $var
5
$ cd $var

この関数を現在のターミナルに配置したり、.bashrcファイルに追加したりすることもできます。

4.2. 一時ファイルと環境変数の使用

コマンドに対して特別なラッパーを実行するのではなく、すべてのコマンドの出力をファイルに格納するためのフックを実装できます。

このソリューションは、環境変数を使用します。

$ PROMPT_COMMAND='touch /tmp/last_command; var="$(cat /tmp/last_command)"; exec >/dev/tty; exec > >(tee /tmp/last_command)'

まず、一時ファイルを作成し、変数名 var を設定します。この変数名は、後で呼び出して出力を取得します。 次に、 / tmp /last_commandにある一時ファイルの内容を出力します。 最初のセミコロンの後、現在のコンソール端末( / dev / tty で表されます)でexecを使用してコマンドを実行します。 最後に、最後のセミコロンの後、パイプを使用した tee コマンドは、標準出力を一時ファイルと画面に送信します。

任意のコマンドの後、出力が自動的に保存されるため、使用法は比較的簡単です。

$ ls *.txt
ax.txt
ay.txt
$ echo $var
ax.txt ay.txt
$ mv $var 5

これは、出力をキャプチャするプロセスを自動化する場合に推奨されるアプローチです。 ただし、このアプローチには2つの欠点があります。

  • 手順は自動であるため、 $ varに複数回依存することはできないことを覚えておく必要があります。 以前とは対照的に、 out2var を明示的に呼び出す必要がありましたが、ここでは1つのコマンドを実行するたびに$varの内容を置き換えます。
  • すべてのコマンドの出力をキャプチャします。これにより、インタラクティブコマンド問題が発生する可能性があります(たとえば、 vim )。

出力の自動保存を停止するには、次のコマンドを実行します。

$ unset PROMPT_COMMAND

5. 結論

この記事では、コマンドの出力を変数に格納するさまざまな方法について説明しました。

この変数を別のコマンドの入力の一部として使用する方法を見ました。

また、コマンド出力をより頻繁にキャプチャするために作成できるいくつかのスクリプトについても説明しました。