9

(t|b|bug_|task_|)1234bash 正規表現を使用して、この形式の文字列の数字をキャプチャするのに問題があります。以下は機能しません。

[[ $current_branch =~ ^(t|b|bug_|task_|)([0-9]+) ]]

しかし、一度次のように変更します。

[[ $current_branch =~ ^(t|b|bug_|task_)([0-9]+) ]]

それは機能しますが、接頭辞がない場合をカバーしていないため、もちろん間違っています。この場合、私はできることを理解しています

[[ $current_branch =~ ^(t|b|bug_|task_)?([0-9]+) ]]

同じ結果が得られますが、2番目の例が機能しない理由を知りたいです。たとえば、その正規表現はRubyでうまく機能するようです。

(これはGNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)、OSX Lion にあります)

4

2 に答える 2

4

正規表現の動作バージョンと非動作バージョンの違いは、さまざまな読み取り方法に基づいていると確信していますregex (7)。問題の核心につながると思うので、関連する部分全体を引用します。


正規表現 (「RE」) は、POSIX.2 で定義されているように、次の 2 つの形式があります: 最新の RE (大まかに egrep のもの。POSIX.2 ではこれらを「拡張された」RE と呼んでいます) と廃止された RE (大まかに ed(1) のもの) です。 ; POSIX.2「基本」RE)。廃止された RE は、主にいくつかの古いプログラムの下位互換性のために存在します。それらについては最後に説明します。POSIX.2 では、RE の構文とセマンティクスのいくつかの側面がオープンのままになっています。"(!)" は、他の POSIX.2 実装に完全に移植できない可能性があるこれらの側面に関する決定を示します。

(最新の) RE は、'|' で区切られた1 つ (!) または複数の空でない (!)ブランチです。ブランチの 1 つに一致するものすべてに一致します。

ブランチは、連結された1 つ (!) 以上のピースです。1 番目の一致に一致し、2 番目の一致が続きます。

ピースはアトムで、その後に 1 つの (!) '*'、'+'、'?'、またはboundが続く可能性があります。'*' が後に続くアトムは、アトムの 0 個以上の一致のシーケンスに一致します。「+」が後に続くアトムは、アトムの 1 つ以上の一致のシーケンスに一致します。アトムの後に「?」アトムの 0 個または 1 個の一致のシーケンスに一致します。

境界は、'{' の後に符号なし 10 進整数が続き、場合によっては ',' が続き、場合によっては別の符号なし 10 進整数が続き、常に '}' が続きます。整数は 0 から RE_DUP_MAX (255(!)) までの整数でなければならず、それらが 2 つある場合、最初の値が 2 番目の値を超えてはなりません。1 つの整数 i を含みコンマを含まない境界が続くアトムは、アトムの正確に i 個の一致のシーケンスに一致します。1 つの整数 i とカンマを含む境界が続くアトムは、アトムの i 個以上の一致のシーケンスに一致します。アトムの後に i と j の 2 つの整数を含む境界が続くと、アトムの i から j (両端を含む) の一連の一致に一致します。

アトムは、"()" で囲まれた正規表現 (正規表現の一致に一致)、"()" の空のセット (null 文字列に一致)(!)、ブラケット式 (以下を参照)、'. ' (任意の 1 文字に一致)、'^' (行頭のヌル文字列に一致)、'$' (行末のヌル文字列に一致)、'\' の後にいずれかの文字が続く " ^.[$()|*+?{\" (通常の文字と見なされるその文字に一致)、'\' の後に他の任意の文字が続く (!) (通常の文字と見なされるその文字に一致し、' \' が存在しなかった (!))、または他の意味を持たない単一の文字 (その文字に一致)。'{' 数字以外の文字が続くのは通常の文字であり、境界 (!) の始まりではありません。'\' で RE を終了することは不正です。


OK、ここには開梱するものがたくさんあります。まず、「(!)」記号は、未解決の問題または移植不可能な問題があることを意味します。

本質的な問題は次の段落にあります。

(最新の) RE は、'|' で区切られた1 つ (!) または複数の空でない (!)ブランチです。

あなたのケースは、空のブランチがあるということです。「(!)」からわかるように、空のブランチはオープンまたは移植不可の問題です。これが、一部のシステムでは機能するが、他のシステムでは機能しない理由だと思います。(私は Cygwin 4.1.10(4) リリースでテストしましたが、動作しませんでした。その後、Linux 3.2.25(1) リリースで動作しました。2 つのシステムには同等のマニュアル ページがありますが、同一ではありません。正規表現7 .)

ブランチが空でない必要があると仮定すると、ブランチはピースである可能性があり、アトムである可能性があります。

アトムは「"()" の空のセット (null 文字列に一致する)(!)」である可能性があります。 <sarcasm>なるほど、本当に助かります。</sarcasm> そのため、POSIX は空文字列の正規表現を指定します。つまり()、「(!)」を追加して、これが未解決の問題、または移植可能でないことを示します。

探しているのは空の文字列に一致するブランチなので、試してください

[[ $current_branch =~ ^(t|b|bug_|task_|())([0-9]+) ]]

これは()正規表現を使用して空の文字列と一致させます。(これは、元の正規表現が機能しなかった Cygwin 4.1.10(4) リリース シェルで機能しました。)

ただし、(願わくは) この提案が現在の設定でうまくいくとはいえ、移植可能であるという保証はありません。がっかりしてごめんなさい。

于 2012-06-18T11:45:56.237 に答える
0

[[ $current_branch =~ ^(t|b|bug_|task_|)([0-9]+) ]]bash 4.1.2では機能しますが、bash3.2.48では失敗します。これは、2つのバージョン間で修正されたバグである可能性があります。

于 2012-05-24T18:54:56.747 に答える