FreeBSDでファイルにESC制御文字を挿入するには?

FreeBSDでファイルにESC制御文字を挿入するには?

Fortranコメントを2つのエスケープコマンド(ESC + EとESC + F)でラップしたいです。これは、接頭辞と接尾辞!だけでなく、行の末尾から始まり、終わるコメントを検出することを意味します。ESC+EESC+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

システムの詳細

オペレーティングシステム: FreeBSD 12.
シェル:sh
Seder:sed

ベストアンサー1

失敗した試み

ここで理解する必要がある2つのレベルがあります。まず、シェルは入力を処理し、それをSedに渡します。

  •  sed 's/\(!.*\)/\033E\1\033F/'
    

    一重引用符は内側のすべての文字の文字通りの意味を維持するため、最初の試みでは、Sedは引用符の間のすべての文字を取得します。

    ただし、Sedが\033ASCII Octal 033(ESC)を理解していないため失敗します。と推測されたかもしれませんが、sed マニュアルそれについて何も言わなかった。

  •  sed $'s/\(!.*\)/\033E\1\033F/'
    

    この$'...'構成はANSI Cリファレンスです。これはシェルが$'\033'ESC文字に変換されるので、これは良い考えです。しかし、Sh FreeBSD マニュアル 有効なバックスラッシュシーケンスを含むリスト

    バックスラッシュで始まるその他の文字列はエラーです。

    リスト\(または\)?いいえ、したがってエラーメッセージが表示されます。また、\1Sedに送るべき内容もASCII Octal 001(SOH)と解釈されますが、これは確かにユーザーが望むものではありません。

解決策

以下のオプション1と2の場合は、\033簡単に書き込むこともできます\e

  1. ANSI引用エスケープ\033シーケンスのみを使用し、残りは一般引用として残します。

    sed 's/\(!.*\)/'$'\033''E\1'$'\033''F/'
        ^^^^^^^^^^^^       ^^^^^       ^^^^
                    ^^^^^^^     ^^^^^^^
    
  2. 一致する文字列全体をキャプチャするためにキャプチャグループは必要ありません。これが&デフォルトです。

    sed $'s/!.*/\033E&\033F/'
    
  3. (POSIX互換)ESCを生成するには、Printfを使用してください。 1つを選択してください

    esc=$(printf '\033'); sed "s/!.*/${esc}E&${esc}F/"
    sed "s/!.*/$(printf '\033')E&$(printf '\033')F/"
    
  4. (POSIX互換) awk.

    awk '{sub(/!.*/, "\033E&\033F"); print}'
    

おすすめ記事