BSD sed に \n や \t のようなエスケープ シーケンスを解釈するように指示するにはどうすればよいですか?

BSD sed に \n や \t のようなエスケープ シーケンスを解釈するように指示するにはどうすればよいですか?

sed私はBSDとGNUの両方と互換性を持たせたいsed代替コマンドを持っています。拡張正規表現は、この場合は必要ないので問題ではありません。私の主な問題は、2つのsが文字エスケープシーケンスを解釈するsed方法の違いです。sed交換文字列。置換文字列にはタブと改行文字が含まれており、メンテナンスを容易にするためにコマンド文字列でそれらを表示したいのですが、BSDはsedエスケープシーケンスを解釈せず、GNUsed するBSD でこれらのエスケープ シーケンスを解釈するための適切な方法は何でしょうか。sed次の 2 つのスニペットが私の問題を象徴しています。

GNUsed

echo ABC | sed 's/B/\n\tB\n'

収穫

A
    B
C

BSDA のsed

echo ABC | sed 's/B\n\tB\n'

収穫

AntBnC

明らかに、BSDではエスケープシーケンスとして解釈されない\n\tsed

さて、私の質問です。BSD のsedマニュアルページによると:

置換文字列に改行文字を指定するには、その前にバックスラッシュを付けます。

これは、私がリテラルバックスラッシュで改行しますか?置換テキストのsedようにエスケープシーケンスを解釈するように指示する適切な方法は何ですか?\n

答え1

文字列を に渡す前に、 bash の$'...'引用符を使用してエスケープを解釈することができますsed

bash のマニュアルページから:

   Words  of  the  form  $'string'  are  treated specially.  The word
   expands to string, with backslash-escaped characters  replaced  as
   specified  by the ANSI C standard.  Backslash escape sequences, if
   present, are decoded as follows:
          \a     alert (bell)
          \b     backspace
          \e     an escape character
          \f     form feed
          \n     new line
          \r     carriage return
          \t     horizontal tab
          \v     vertical tab
          \\     backslash
          \'     single quote
          \nnn   the eight-bit character whose  value  is  the  octal
                 value nnn (one to three digits)
          \xHH   the eight-bit character whose value is the hexadeci-
                 mal value HH (one or two hex digits)
          \cx    a control-x character

   The expanded result is single-quoted, as if the  dollar  sign  had
   not been present.

   A  double-quoted  string  preceded by a dollar sign ($) will cause
   the string to be translated according to the current  locale.   If
   the  current locale is C or POSIX, the dollar sign is ignored.  If
   the string is translated and replaced, the replacement is  double-
   quoted.

答え2

移植可能なスクリプトを書く必要がある場合は、POSIX標準(別名 Single Unix、別名 Open Group Base 仕様)。問題 7 別名 POSIX-1.2008は最新ですが、多くのシステムではまだ導入が完了していません。問題 6 別名 POSIX-1.2001概して、すべての最新のユニックスによって提供されています。

sed\t、およびのようなエスケープシーケンスの意味は\n正規表現\n改行を表します。コマンドの置換テキストではs\nは移植性がありませんが、バックスラッシュ-改行のシーケンスを使用して改行を表すことができます。

タブ文字(または8進数で表現される他の文字)を生成するための移植性の高い方法は、tr文字をシェル変数に格納し、この変数を sed スニペットで置き換えます。

tab=$(echo | tr '\n' '\t')
escape=$(echo | tr '\n' '\033')
embolden () {
  sed -e 's/^/'"$escape"'[1m/' -e 's/$/'"$escape"'[0m/'
}

s正規表現と置換テキストでは改行を異なる方法で表現する必要があることに再度注意してください。

使用したい場合がありますawk\ooo代わりに、すべての文字列リテラルで、8 進エスケープを含むバックスラッシュ エスケープが許可されます。

答え3

これについては Stack Overflow で回答されています:

https://stackoverflow.com/questions/1421478/how-do-i-use-a-new-line-replacement-in-a-bsd-sed

jw013 が言ったこととほぼ同じです。

リテラルタブを挿入するには、ctrl+と入力しますVTab

関連情報