Fortranコメントを2つのエスケープコマンド(ESC + EとESC + F)でラップしたいです。これは、接頭辞と接尾辞!
だけでなく、行の末尾から始まり、終わるコメントを検出することを意味します。ESC+E
ESC+F
最初の試み
$ echo "test line ! Enclose this in ESC commands" | sed 's/\(!.*\)/\033E\1\033F/'
test line 033E! Enclose this in ESC commands033F
ESC文字自体は生成されず、代わりに033が表示されます。
2回目の試み
$ echo "test line ! Enclose this in ESC commands" | sed $'s/\(!.*\)/\033E\1\033F/'
sh: Syntax error: Bad escape sequence
システムの詳細
答え1
失敗した試み
ここで理解する必要がある2つのレベルがあります。まず、シェルは入力を処理し、それをSedに渡します。
-
sed 's/\(!.*\)/\033E\1\033F/'
一重引用符は内側のすべての文字の文字通りの意味を維持するため、最初の試みでは、Sedは引用符の間のすべての文字を取得します。
ただし、Sedが
\033
ASCII Octal 033(ESC)を理解していないため失敗します。と推測されたかもしれませんが、sed マニュアルそれについて何も言わなかった。 -
sed $'s/\(!.*\)/\033E\1\033F/'
この
$'...'
構成はANSI Cリファレンスです。これはシェルが$'\033'
ESC文字に変換されるので、これは良い考えです。しかし、Sh FreeBSD マニュアル 有効なバックスラッシュシーケンスを含むリストバックスラッシュで始まるその他の文字列はエラーです。
リスト
\(
または\)
?いいえ、したがってエラーメッセージが表示されます。また、\1
Sedに送るべき内容もASCII Octal 001(SOH)と解釈されますが、これは確かにユーザーが望むものではありません。
解決策
以下のオプション1と2の場合は、\033
簡単に書き込むこともできます\e
。
ANSI引用エスケープ
\033
シーケンスのみを使用し、残りは一般引用として残します。sed 's/\(!.*\)/'$'\033''E\1'$'\033''F/' ^^^^^^^^^^^^ ^^^^^ ^^^^ ^^^^^^^ ^^^^^^^
一致する文字列全体をキャプチャするためにキャプチャグループは必要ありません。これが
&
デフォルトです。sed $'s/!.*/\033E&\033F/'
(POSIX互換)ESCを生成するには、Printfを使用してください。 1つを選択してください
esc=$(printf '\033'); sed "s/!.*/${esc}E&${esc}F/" sed "s/!.*/$(printf '\033')E&$(printf '\033')F/"
(POSIX互換) awk.
awk '{sub(/!.*/, "\033E&\033F"); print}'