sed 条件付き分岐 "t" は、最後の置換が失敗した場合でも分岐し続けます。

sed 条件付き分岐

次のsed式があります。

echo 'abcabcabc' | sed -n ':-A s/a/x/1; s/a/&/2;t-A; p'

最後の項目を除くすべての項目と'a'交換する必要があるとします'x'。したがって、予想される結果は次のとおりです。

xbcxbcabc

ただし、実際の出力は次のようになります。

xbcxbcxbc

すべて'a'次へ交換'x'

私はすでに、次のような質問があることを知っています。 各行の最後の文字を除くすべての文字を置き換える

しかし、ここではsed条件分岐を使用して別のアプローチを試しています。

私自身の理解を使って私のsed表現を分析しましょう。

最初のものはsed式です。

echo 'abcabcabc' | sed -n ':-A s/a/x/1; s/a/&/2;t-A; p'

abcabcabcsed を使用してパターン空間にインポートします。

次にラベルを設定します。:-A

次に、s/a/x/1;最初の項目'a''x'。これで、パターン空間には以下が含まれます。xbcabcabc

s/a/&/2;パターンスペースに両方が含まれていることを確認して、両方をそれ自体に置き換えます'a'。したがって、パターン空間は依然として次のものを含む。'a'&xbcabcabc

t-A最近の交換が成功したため、ラベルに戻ります。-A

タグから始めて-Aこれをやり直し、s/a/x/1;パターンスペースの内容をこれからxbcabcabcこれに変更します。xbcxbcabc

s/a/&/22つ以上があることを確認してください'a'。今回はパターンスペースにこれが含まれていますが、xbcxbcabc2つはないため、'a'置換は失敗します。

t-Aなぜなら、最近交換したのは失敗する、ラベルにジャンプしてはいけませんが、パターンスペースの内容を印刷し続け、終了する必要があり-Aます。しかし、代わりに交換が行われてもpxbcxbcabc失敗するもう一度タグに戻り、-A残りの部分を'a'置き換えます'x'。だから結果はこれですxbcxbcxbc

l式の間に挿入する場合:

 echo 'abcabcabc' | sed -n ':-A s/a/x/1;  l; s/a/&/2;t-A; p'

出力:

xbcabcabc$
xbcxbcabc$
xbcxbcxbc$
xbcxbcxbc$
xbcxbcxbc

パターン空間にこれが含まれていても、再分岐することがわかります。xbcxbcabc

それでは、私がここで何を見逃しているのでしょうか?

ベストアンサー1

s/a/&/22番目のものをそれ自体で置き換えることに注意してくださいa。 。a言い換えれば、常に(最初のものを次に置き換える)と同じですs/a/x/1。これは質問とは関係ありませんが、まだ他の状況であなたを悩ませる可能性がある誤解です。s/a/x/ax

GNUマニュアルによれば、t最後の入力ラインを読んだ後に成功した置換が発生した場合、コマンドは分岐しますt。ただし、それ以降に他のコマンドがトリガされない限りは次のとおりです。sed

t label
s///最後の入力行を読んだ後、aが正常に置き換えられた場合に分岐し、最後またはcommandを省略するとスクリプトの最後に分岐します。tTlabellabel

同じコマンドのPOSIX仕様これに同意します。

[2addr]t [label]
テスト。最後の入力行を読み取りまたは:実行しlabelた後に置換が行われたかどうかを使用して、コマンド動詞に分岐しますt。指定しない場合は、labelスクリプトの最後に分岐します。

要約すると、単一の入力行に対してコマンドが成功すると、最後のコマンド以降はs常に指定されたラベルに分岐しますtt

あなたのデータは最初に変換され、次に変換さxbcabcabcれますxbcxbcabc。この結果が得られると、s反復の最初のコマンドは最初のコマンドをaに正常に置き換えるため、コマンドブランチがxとして指定されます。txbcxbcxbc

この問題を解決する1つの方法は、追加のtコマンドとダミーラベルを挿入することです。

echo abcabcabc |
sed -e :A -e 's/a/x/'  -e tB \
    -e :B -e 's/a/&/2' -e tA

tB最初のコマンドの「リセット成功フラグ」を実行しますs

おすすめ記事