シェル スクリプトのこの行を理解しようとしています。$(..)
を実行して..
、その出力を$()
ステートメント内の該当する場所に挿入するという意味であることはわかっています。しかし、括弧の間では何が起こっているのでしょうか。 は何をしていて、前の行\ls
の とどのように関係しているのでしょうか。 2 行に分割されていますか。通常の と同じですか。\
\\
\ls
ls
APPCLASSPATH=$CLASSPATH:$({ \
\ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \
\ls -1 "$VOLTDB_LIB"/*.jar; \
\ls -1 "$VOLTDB_LIB"/extension/*.jar; \
} 2> /dev/null | paste -sd ':' - )
答え1
3 つのコマンドからの出力は、それらを値にマージするコマンドls
に渡されます。paste
$VOLTDB_VOLTDB"/voltdb-*.jar:$VOLTDB_LIB"/*.jar:$VOLTDB_LIB"/extension/*.jar
注記:変数$VOLTDB_VOLTDB
とが展開され、これらのコマンド$VOLTDB_LIB
ごとに 1 つのファイルよりも多くの値が存在する可能性があります。そこにありますか? これはワイルドカードとして機能する glob 文字で、たとえば左側 (voltdb-) と右側 (.jar) の間の任意の値に展開されます。ls
*
これらは一致します:
voltdb-1.jar
voltdb-blah.jar
voltdb-12345.jar
すべてが変数に含まれますAPPCLASSPATH
。
APPCLASSPATH=$CLASSPATH:$VOLTDB_VOLTDB"/voltdb....etc.
貼り付けコマンド
seq
以下は、コマンドを使用して 1 ~ 10 の数字のシーケンスを生成する例です。
$ seq 10 | paste -sd ':' -
1:2:3:4:5:6:7:8:9:10
paste
コマンドが出力をマージし、コロン ( ) で区切っていることがわかります:
。
次のようにして例のコマンドを模倣することもできます。
$ { echo "hi1"; echo "hi2"; echo "hi3"; } | paste -sd ':' -
hi1:hi2:hi3
注記:paste コマンドのto-
は、STDIN から入力を取得し、各引数を . で区切って入力順に印刷するように指示します:
。
さまざまなスイッチを使用すると、その後の「」paste
の数に基づいてデータをグループに分割することもできます。-
貼り付け例
ここに 2 の例を示します-
。
$ seq 10 | paste - -
1 2
3 4
5 6
7 8
9 10
ここに 3-
があります。
$ seq 10 | paste - - -
1 2 3
4 5 6
7 8 9
10
つまり、各行にいくつpaste
の引数を出力するかを指定していることになります。ただし、混乱しないでください。ここで扱っている例は、単に STDIN から入力を取得し、各引数をスペースで区切って、その後に を出力しているだけです。 を複数指定すると、一度に 2 つ、一度に 3 つなど、引数を取得するように指示していることになります。paste
:
-
paste
引数は一度に 2 つ、:
's で区切られます。
$ seq 10 | paste -d ':' - -
1:2
3:4
5:6
7:8
9:10
$ seq 10 | paste -d ':' - - -
1:2:3
4:5:6
7:8:9
10::
ちなみに、スイッチを含めると、引数を連続して(シリアルに)受け取るように-s
指示することになりpaste
ます。上記の例の 1 つでこれを使用した場合に何が起こるかを確認してください。
一度に2つ:
$ seq 10 | paste -sd ':' - -
1:2:3:4:5:6:7:8:9:10
一度に3つ:
$ seq 10 | paste -sd ':' - - -
1:2:3:4:5:6:7:8:9:10
答え2
$(command)
コマンドを実行し、その出力を置き換えます。
{ list; }
はグループ コマンドであり、現在のシェル環境で複数のコマンドを実行します。 に似ています(list)
が、サブシェルを作成しません。
\command
コマンドのエイリアスを無視するために使用されます。エイリアスにより、コマンドの予想される動作が大幅に変更される可能性があります。
行末のは\
、単にこの行が継続することを意味するため、シェルは次の行を現在の行の一部として認識します。通常、コンテキストからこれが明らかな場合 (開き括弧または引用符) は必要ありません。
答え3
APPCLASSPATH=$CLASSPATH:$({ \ \ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \ \ls -1 "$VOLTDB_LIB"/*.jar; \ \ls -1 "$VOLTDB_LIB"/extension/*.jar; \ } 2> /dev/null | paste -sd ':' - )
\ls
は と似ていますls
が、ls
がエイリアスの場合、バックスラッシュによってエイリアスの展開が防止されます。これにより、コマンドが使用され、分類子サフィックス ( )ls
などの不要な出力を追加する可能性のあるエイリアスは使用されないことが保証されます。-F
ls
既存のファイル名を引数として呼び出されるコマンドは、1 行に 1 つずつ引数をリストします。 の出力はターミナルではなくパイプに送られるため、 のオプションは効果が-1
ありません。が既存のファイルの名前ではない引数を受け取った場合、標準出力には何も表示されず、代わりにエラーが表示されます。 コマンドからのエラーは によってどこにもリダイレクトされません。 がファイルではない引数を受け取る理由は 2 つあります。変数の 1 つが既存の読み取り可能なディレクトリを参照していない場合、またはワイルドカード パターンに一致するファイルがない場合です。どちらの場合も、パターンは展開されずに に渡されます。ls
ls
ls
2> /dev/null
ls
ls
行末のバックスラッシュにより、シェルは後続の改行を無視します。バックスラッシュが使用されているすべてのポイントで、シェルはオプションの改行を期待しているため、ここではバックスラッシュはどれも役に立ちません。
中括弧 { … } はコマンドをグループ化します。複合コマンド{ \ls …; \ls …; \ls … ; }
は にパイプされpaste
、そのエラーは にリダイレクトされます/dev/null
。
このpaste
コマンドは、間に を入れてすべての入力行を結合します。末尾にを付けないことを除いて、:
と同じです。tr '\n' :
:
コマンド置換により、$(…)
の出力paste
が に補間されAPPCLASSPATH
、変数 の値の後にCLASSPATH
コロンが挿入されて 2 つの部分が区切られます。
簡略化されたバージョンを以下に示します。ワイルドカード パターンのいずれも一致しない場合は、末尾のコロンがなくてもAPPCLASSPATH
等しくなります(おそらくこれが望ましいでしょう)。この点で、オリジナルとは少し異なります。CLASSPATH
APPCLASSPATH=$CLASSPATH:$(
\ls "$VOLTDB_VOLTDB"/voltdb-*.jar "$VOLTDB_LIB"/*.jar "$VOLTDB_LIB"/extension/*.jar |
tr '\n' :) 2>/dev/null
APPCLASSPATH=${APPCLASSPATH%:}