今日、私はbashスクリプトを書いて驚くべきことを見つけました。私はこれを最小限の例にまとめました。
[[ a>b ]]; echo $?
私の理解によると、周囲にスペースがないので、>
文字列が空でないことをテストし、a>b
エラーコードを返す必要があります0
。ただし、上記のコマンドは1
テストした両方のbashバージョンでエコーされます(詳細は以下を参照)。
また、以前の「good」コマンドを使用してtest
テストしました。
[ a>b ]; echo $?
echo 0
(文字列がa
空でないことをテストし、b
現在の作業ディレクトリに空のファイルを作成します。>b
これは明らかにリダイレクトとして扱われ、理解できます)。
それからいくつかの他のことを試しました。
[[ b>a ]]; echo $?
エコーが発生0
し、ファイルは生成されません。[[ b<a ]]; echo $?
エコーが発生1
し、ファイルは生成されません。[[ a<b ]]; echo $?
エコーが発生0
し、ファイルは生成されません。[ b>a ]; echo $?
エコー0
して空のファイルを作成しますa
。[ b<a ]; echo $?
不足しているファイルのエラーを報告し、そのa
エラー1
のためにエコーされます。[ a<b ]; echo $?
不足しているファイルのエラーを報告し、そのb
エラー1
のためにエコーされます。[[ a=b ]]; echo $?
期待どおりに0
文字列が空でないことをテストするため、エコーされます。a=b
[ a=b ]; echo $?
0
同じ理由でエコ。[[ a==b ]]; echo $?
0
同じ理由でエコ。[ a==b ]; echo $?
0
同じ理由でエコ。[[ a!=a ]]; echo $?
どちらも[ a!=a ]; echo $?
エコ0
(予想)
<
したがって、条件式では and の周囲の空白だけを省略できるように見えますが、文字列比較を行うことが目的の場合は省略できません。しかし、なぜこのように設計されたのでしょうか。これは私が見逃したものかもしれませんが、bashマニュアルのどこにも文書化されていないようです。>
=
==
!=
私の最初の問題は、条件式()のパターンの一部として>
エスケープされていないものを使用しようとすることでした。[[ ... ]]
私は最初にスペースで囲まない限り>
問題なく使用できると思いました。条件付きでリダイレクトすることは意味がないからです(そして一部のテストが不可能であることが判明した後)、式は機能します。また。
しかし、これは真実ではないことが判明しました。もちろん簡単な解決策はエスケープ処理し>
て作成する\>
ことですが、なぜ必要なのか理解できません。
これはテストに使用したbashバージョンです。
GNU bash, version 5.2.2(1)-release (aarch64-unknown-linux-android)
そして
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
私の実験はenv -i bash --norc --noprofile
。
答え1
&
これは、、、、、、、、タブなどの文字;
です(
。|
<
>
メタ文字シェル構文から。それらは独自のトークンを形成します(またはより多くのトークンに結合することができます(たとえば、、、;;
... |&
)||
。これは、文字²と数字が似ている、、、、[
などの{
文字とは異なります。!
-
=
Korn シェルの構成内では、[[...]]
シェルは別個のマイクロ言語を理解していますが、外部とほぼ同じマークアップ規則に従います。
同じ理由で、外部では[[...]]
次のことができます。
(echo a>file|tr a b&)
そしてそれを書く必要はありません:
( echo a > file | tr a b & )
それともそのようなものですif((1))then<file&&(uname)fi
。
ここでは、次のことができます。
[[(a>b||b<d)]]
(
、および>
はシェルメタ文字|
です)
。
メタ文字を文字通り解釈するには、引用符('...'
、、、、...を含む)で囲む必要があります"..."
。\
$'...'
[[x]]
シェルは1つの[[x]]
トークンしか表示できないため、機能しません。そして、構成を[[
開始するキーワード[[...]]
も認識されません。マイクロ言語と[[ a==b ]]
は異なり、単一のトークンなので、解釈はと同じです。[[ a == b ]]
[[...]]
a==b
[[ -n 'a==b' ]]
[
それ自体は単なる一般的なコマンドなので、他のコマンドと同じ方法で解析されます。
[ a>b ]
[
a
引数で実行すると、]
出力はwithまたは同様にリダイレクトされb
ます。[ a ] > b
echo a>b ]
echo a ] > b
>b echo a ]
内部的には((...))
(kshとは異なり)Cに似た独自のマイクロ言語が提供されていますが、今回はトークン化規則が異なります。たとえば、((var=123+1))
orを書くことができますが、orは必要((a==b))
ありません。((var = 123 + 1))
((a == b))
1は{
中括弧拡張に参加し、シェル予約語でもありますが、トークン化後に処理されますが、割り当てを[
解析するときにトークン化に参加します。引数として実行されずa[1 + 1]=foo
、bashまたはksh(zshではない)から割り当てられた単語として解析されます。a[1
はのような予約語ですが、履歴の拡張にも参加します。ただし、これはシェルの対話型呼び出しにのみ適用されます。+
1]=foo
!
{
-
²一部の演算子には文字が含まれていることに注意してください。[[...]]
たとえば-nt
、、、...-eq
-lt