sedとawkによる置換の戻り値
1. 概要
Linuxでは、戻り値を確認することで、コマンドが正常に実行されたかどうかを判断できます。 通常、ゼロ以外の数値が返された場合、コマンドは失敗したと見なされます。
sedまたはawk、でテキスト置換を行う場合、リターンコードを介してそこで正常に置換されたかどうかを知りたい場合があります。
このチュートリアルでは、置換結果に応じて異なる値を返す方法を学習します。
2. 問題の紹介
まず、例を見てみましょう。
$ sed 's/Java/Kotlin/' <<< 'Java is awesome!'
Kotlin is awesome!
$ echo "return code is $?"
return code = 0
上記の例が示すように、 sed コマンドを使用して、1行の文字列のテキストを置き換えることができました。 また、当然のことながら、戻り値はゼロになっています。
次に、別の例を見てみましょう。
$ sed 's/Windows/Linux/' <<< 'Java is awesome!'
Java is awesome!
$ echo "return code is $?"
return code = 0
今回は、 sed コマンドを使用して、「Windows」を「Linux」に置き換えようとしました。 また、入力文字列には置換しようとしているパターン(“ Windows “)が含まれていないため、コマンドで置換を実行する必要はありません。したがって、sedからの出力文字列はは入力と同じです。
ただし、この例の echo 出力からわかるように、sedコマンドの戻り値はまだゼロでした。 これは、置換(s /…/…/)は何も変更しなかったものの、sedコマンドの実行自体は成功したためです。
ただし、sedやawkなどの置換を含むコマンドを実行した後、戻りコードをすばやく確認して、置換が成功したかどうかを知りたい場合があります。
したがって、入力が検索パターンと一致しない場合に置換が失敗したことを示すために、 sedとawkがゼロ以外の値(たとえば100)を返す方法について説明します。
単一行入力と複数行入力の2つのシナリオについて説明します。
また、チュートリアルでは、GNU awkとGNUsed を使用します。これらは、Linuxオペレーティングシステムで広く使用されているためです。
3. 単一行入力
シェルスクリプトを作成するとき、1行の文字列を「検索して置換」することで変数の値を変更することがよくあります。
3.1. sedコマンドの使用
sedコマンドには’q ‘コマンドがあり、 sed スクリプトを終了して、それ以上の入力の処理を停止します。 GNU sed は、「q」コマンドに対する[exit-code]引数をサポートします。
したがって、「q [exit-code]」コマンドを呼び出すことにより、戻り値をカスタマイズできます。次に例を示します。
$ sed 'q 100' <<< 'Java is awesome!'
Java is awesome!
$ echo "return code is $?"
return code is 100
次に、指定された正規表現がパターンスペースに一致する場合、が置換を実行し、終了コード0を返すことを確認します。一致しない場合は、終了コード100でsed処理を終了します。
$ sed '/Java/!{q100}; {s/Java/Kotlin/}' <<< 'Java is awesome!'
Kotlin is awesome!
$ echo "return code is $?"
return code is 0
$ sed '/Windows/!{q100}; {s/Windows/Linux/}' <<< 'Java is awesome!'
Java is awesome!
$ echo "return code is $?"
return code is 100
上記の出力でわかるように、問題は解決しました。
3.2. sedコマンドの改善
まず、sedソリューションをもう一度見てみましょう。
コマンドで正規表現を2回繰り返しました。 1つは一致チェック用で、もう1つは s/../../コマンド用です。
このコマンドをシェルスクリプトに含めると、さらにメンテナンスを行うために余分な労力がかかる可能性があります。 正規表現を調整する必要がある場合は、正確な変更を2回行う必要があります。
簡単な改善は、正規表現を変数に保存することです。 次に、変数を使用してsed置換を実行できます。
実際には、sedの’t ‘コマンドを使用して、追加の変数なしで正規表現の重複を削除できます。
$ sed 's/Java/Kotlin/; ta; q 100; :a' <<< 'Java is awesome!'
Kotlin is awesome!
$ echo "return code is $?"
return code is 0
$ sed 's/Windows/Linux/; ta; q 100; :a' <<< 'Java is awesome!'
Java is awesome!
$ echo "return code is $?"
return code is 100
sedの「ta」コマンドは、前のs /../../が正常に置換された場合、処理をラベル(この場合は「a」)に分岐できます。
上記の例では、置換が成功すると、 sedはラベル’:a‘にジャンプします。これはsedコマンドの終わりです。 したがって、コマンドはゼロで終了します。
ただし、 s /../../ が成功しなかった場合、「ta」コマンドは何もしません。 したがって、「 q 100 」が実行され、sedがコード100で終了します。
3.3. awkコマンドの使用
sedの’q [exit-code] ‘と同様に、awkにはexit[expression]コマンドがありを終了します。 ]awkスクリプト。「exit100」などの戻り値があります。
また、 awk には、テキスト置換用の sub()およびgsub()関数があります。 さらに、関数は成功した置換の数を返します。
したがって、 sub()または gsub()関数の戻り値をチェックすることで、置換が成功したかどうかをすばやく判断できます。
$ awk '{ v=sub(/Java/, "Kotlin"); print } v==0 { exit 100 }' <<< 'Java is awesome!'
Kotlin is awesome!
$ echo "return code is $?"
return code is 0
$ awk '{ v=sub(/Windows/, "Linux"); print } v==0 { exit 100 }' <<< 'Java is awesome!'
Java is awesome!
$ echo "return code is $?"
return code is 100
ご覧のとおり、awkソリューションはsedソリューションよりも簡単です。
4. マルチライン入力
複数行の入力にも置換を適用することがよくあります。 サンプルファイルを作成しましょう:
$ cat input.txt
Java is a programming language.
Java is awesome!
Hello World.
次に、置換結果に応じて戻り値を制御する方法を見てみましょう。
今回は、まずawkを使って問題を解決しましょう。
4.1. awkコマンドの使用
awkのsub()および gsub()関数は、成功した置換の数を返すことを学びました。
複数行の入力を処理する場合、各入力行の置換関数の戻り値を累積して、少なくとも1つの成功した置換があるかどうかを判断できます。
$ awk '{ v += sub(/Java/, "Kotlin"); print } END{ if(v==0) exit 100 }' input.txt
Kotlin is a programming language.
Kotlin is awesome!
Hello World.
$ echo "return code is $?"
return code is 0
$ awk '{ v += sub(/Windows/, "Linux"); print } END{ if(v==0) exit 100 }' input.txt
Java is a programming language.
Java is awesome!
Hello World.
$ echo "return code is $?"
return code is 100
上記のawkコマンドは、単一行のソリューションと非常によく似ています。 変更点は2つだけです。
- v = sub()の代わりに v + = sub()を使用して、各行の戻り値を累積します
- 「v==0」チェックをENDブロックに移動して、すべての入力行を処理した後の終了コードを判別します。
これまで見てきたように、awkコマンドは非常に理解しやすいものです。 したがって、最初にawkソリューションについて説明します。
sedでも問題を解決できます。 それがどのように行われるか見てみましょう。
4.2. sedコマンドの使用
sed は、変数の宣言と数学計算の実行をサポートしていません。 したがって、問題を別の方法で解決する必要があります。
まず、解決策を見てみましょう。
$ sed -n 's/Java/Kotlin/; tOK; bNOK; :OK;H; :NOK;p;${g;/./!{q100}}' input.txt
Kotlin is a programming language.
Kotlin is awesome!
Hello World.
$ echo "return code is $?"
return code is 0
$ sed -n 's/Windows/Linux/; tOK; bNOK; :OK;H; :NOK;p;${g;/./!{q100}}' input.txt
Java is a programming language.
Java is awesome!
Hello World.
$ echo "return code is $?"
return code is 100
コマンドを実行する前に、いくつかのsedコマンドを理解する必要があります。
- b label –前の s /../../ が成功したかどうかを確認せずに、指定されたlabelに分岐します
- H –パターンスペースをホールドスペースに追加します
- g –ホールドスペースをパターンスペースにコピーします
次に、コマンドがどのように機能するかを理解しましょう。
4.3. sedソリューションを理解する
「フローチャート」は、それをより簡単に理解するのに役立つ場合があります。
┌──────────────────────┐
┌───success─:OK──────>┤H; p; ${g;/./!{q100}} │
│ ^ └──────────────────────┘
│ │
sed -n 's/Java/Kotlin/; tOK; bNOK; :OK;H; :NOK; p;${g;/./!{q100}}' input.txt
│ │
│ v ┌───────────────────┐
└─not success─┴:NOK──>┤ p;${g;/./!{q100}} │
└───────────────────┘
上のグラフが示すように、置換後のパスは2つあります。 最初に成功事例を見てみましょう。
‘ tOK; ‘コマンドは、処理をルーティングして’H;を実行します。 p; $ {g; /。/!{q100}} ‘:
- H –現在のパターンスペースをホールドスペースに追加して、ホールドスペースが空にならないようにします。 このトリックを使用して、少なくとも1つの成功した置換がある場合にマークを付けます
- p –パターンスペースを印刷します
${。。 –現在の行が入力の最後の行である場合- g –ホールドスペースを現在のパターンスペースにコピーして、少なくとも1つの置換が成功したかどうかを確認できるようにします
.. /./!{q100} } – 保留スペースが空の場合、正常な置換は行われていないと考えられるため、次を返します。 q100
‘NOK‘パスは’OK‘パスに似ています。 ‘ bNOK; ‘コマンドは、次のコマンドに分岐します。’ p; $ {g;/./!{q100}}‘。
したがって、「 OK 」パスとほぼ同じことを行いますが、スペースを保持するためにパターンスペースを追加しません。 これは、変電所が成功した後にのみホールドスペースにマークを設定するためです。
sedソリューションとawkソリューションを比較すると、awkソリューションの方がはるかに理解しやすくなっています。
したがって、入力が複数行の場合、awkソリューションを使用して戻り値を制御することをお勧めします。
5. 結論
この記事では、awkおよびsedの置換が失敗した後にゼロ以外の値を返す方法について説明しました。
また、単一行および複数行の入力シナリオについても説明しました。