これは問題を示すテストファイルだけです。元の部分は次のようになりました。
arch systemd[908]:
これで、閉じ括弧を「:」文字に置き換えることができます。
krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/]/:/g
arch systemd[908::
開いているブラケットを交換しようとすると機能しません。
krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/[/:/g
sed: -e expression #1, char 7: unterminated `s' command
その後、1\文字で「[」をエスケープしましたが、まだ機能しません。
krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/[/:/g
sed: -e expression #1, char 7: unterminated `s' command
2つの「\」を使用してください。
krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/\\[/:/g
arch systemd:908]:
私の質問は次のとおりです。
- 右ブラケットでは機能しますが、左ブラケットでは機能しないのはなぜですか? sedまたはbashがこれを読む方法の違いは何ですか?
- 右角かっことうまく機能し、まったくエスケープする必要はありませんが、左角かっこを2回エスケープする必要があるのはなぜですか?
私はこれを理解したいと思います。これでこれを行う方法を知っていますが、詳細を知らないことに満足していません。
答え1
sed
これはsed式を引用しなかったためです(悪い考えです。コマンドを一重引用符で囲む習慣があります)。エスケープする必要があるのは、正規表現で特別な意味を持ち、文字クラスを開くこと[
です(たとえば、またはいずれかと一致します)。 sedは以前に閉じることがないので、この場合、文字クラスが閉じられないことを知るほどスマートなので、脱出する必要はありません。[
[abc]
a
b
c
]
]
[
これはsed式を引用していないので、これはシェルがそれを解釈しようとすることを意味します。今後に渡しますsed
。したがって、シェルはユーザーの文字を表示し、\[
エスケープされていない文字をsedに渡します。これにより、これを実際に確認できますset -x
。
$ set -x
$ sed s/\[/:/g jctl.log
+ sed 's/[/:/g' jctl.log
sed: -e expression #1, char 7: unterminated `s' command
ご覧のとおり、実行される実際のコマンドはsed 's/[/:/g' jctl.log
次のとおりですsed 's/\[/:/g' jctl.log
。シェルはエスケープ文字を使用しました。その後、sedはターミネータを探していますが、見つから]
ないため失敗します。したがって、文字列全体を/:/g
文字クラスの内容として扱うため、コマンドの終わりが見つからないため失敗しますs///
。
2番目のエスケープレベルを追加すると、シェルは最初のエスケープレベルを使用してから、まだエスケープを[
sedに渡すことができます。
$ sed s/\\[/:/g jctl.log
+ sed 's/\[/:/g' jctl.log
arch systemd:908]:
上記の出力から、\[
sedの代わりにsedが提供されていることがわかります[
。
常に sed コマンドを引用すると、次の問題はすべて消えます。
$ sed 's/\[/:/g' jctl.log
arch systemd:908]: