@ SnoringFrogのトピック作成リクエストから引用するには:
「sedを使用している最大の悪夢の1つは、それらが1つではなく別のもので書かれているため、失敗する(または予期せぬ方法で成功する)スクリプトです。
macOSはBSD版のsed
[1]を使用しています。これは、 Linuxディストリビューションに付属しているGNU sed
バージョンとは多くの点で異なります。
それらの共通の分母はPOSIXによって宣言された機能です: POSIX sed
specを見てください。
もっとも移植性の高いアプローチは、 POSIX機能のみを使用することですが、 機能には限界があります 。
特に、POSIXでは、多くの制限がある基本正規表現 (例えば、 |
(交替)はまったくサポートされておらず、 +
と?
直接サポートしてい?
)と異なるエスケープ要件のみをサポートしています。
sed
( -r
なし) は \|
サポートしています\|
、 \+
と\?
POSIX準拠ではありません。無効にするには--posix
を使います (下記参照)。 POSIX機能のみを使用するには :
(両方のバージョン):- -n
と-e
オプションのみを使用します(特に、 拡張正規表現のサポートを有効にするには-E
または-r
を使用しないでください)
GNU sed
:POSIXのみの機能を確実にするためのオプション--posix
を追加する(これは厳密には必要ではないが、それがなければ非POSIX機能を気付かずに使用することになる可能性がある; - 注意 :-- --posix
自体はPOSIX準拠ではない )
POSIXのみの機能を使うことは、より厳密なフォーマット要件を意味します(GNU sed
利用可能な多くの利便性)。
\n
や\t
などの制御文字列は、一般的にはサポートされていません。 b
)の後には、 実際の改行や、別の-e
オプションによる継続が続かなければなりません 。 しかし、 どちらのバージョンもPOSIX標準への拡張を実装しています。
sed
はもっと多くを実装しています)。 両方のプラットフォームをサポートする必要がある場合(相違点の説明)
互換性のない機能:
引数なしで -i
オプションを使用する(バックアップなしのインプレース更新)は互換性がありません。
sed
: -i ''
使用しなければならないsed
: -i
だけを使用しなければならない( -i''
と同等) -i ''
を使うと動作しない。 -i
は、 GNU sed
と最近のバージョンのBSD sed
(FreeBSD 10など)では入力ファイルごとの行番号付け を有効にしますが、10.12以降のmacOSでは有効にしません 。
-i
が指定されていない場合は、 すべてのバージョンが入力ファイルに累積的に番号を-i
ことに注意してください。
最後の入力行に改行がない場合(および出力された場合):
sed
:入力行が1つで終わっていなくても、常に出力に改行を追加します 。 sed
: 後続改行ステータスを保持します 。つまり、入力行が1つに終わる場合にのみ改行を追加します。 共通の機能:
sed
スクリプトをBSD sed
サポートしているものに制限すると、それらは-E
プラットフォーム固有の拡張正規表現機能を使用するという顕著な例外を除いて、一般にGNU sed
でも動作します。明らかに、GNU版特有の拡張機能も忘れてしまいます。次のセクションを参照してください。 クロスプラットフォームサポート (OS X / BSD、Linux)のガイドラインは、BSDバージョンのより厳しい要件に基づいています 。
なお、速記のMacOSとLinuxは時折のBSDやGNUのバージョンを参照するために以下で使用されていることをsed
、彼らがそれぞれのプラットフォーム上での在庫のバージョンがあるため、それぞれ、。をしかし、 brew install gnu-sed
を使ってHomebrewを使って、macOSにGNU sed
をインストールすることは可能です。
注意 : -r
と-E
フラグが使用されている場合 ( 拡張正規表現)を除いて、以下の手順はPOSIX準拠の sed
スクリプトの作成になります。
POSIX準拠の場合は、 POSIX BRE( 基本正規表現)に制限する必要があります。これは残念なことに、名前が示すように非常に基本的なものです。
警告 :それを想定しない\|
、 \+
と\?
サポートされています:-- --posix
が使われていない限り、GNU sed
サポートしていますが、BSD sed
はそうではありません - これらの機能はPOSIXに準拠していません 。
\+
と\?
POSIX準拠の方法でエミュレートできます 。
\{1,\}
は\+
、
\{0,1\}
は\?
、
\|
残念なことに、 (代替) できません 。
より強力な正規表現については、 使用-E
(というより-r
のERE( 拡張正規表現)(GNUのサポートするために) sed
記述されていません-E
、それはの別名としてそこに働くん-r
、BSDの新しいバージョンsed
FreeBSD 10などでも-r
サポートしていますが、10.12以降のmacOSバージョンはサポートしていません )。
警告 : -r
/ -E
使用は、あなたのコマンドがPOSIXに準拠していないことを意味しますが、 POSIX ERE(拡張正規表現)に制限する必要があります。残念なことに、これはあなたがいくつかの有用な構成を使用することができないことを意味します。
\<
Linux上、 [[:<]]
OS X上)。 sed
は拡張正規表現でそれらをサポートしていないので( 正規表現の中での逆参照は(関数の呼び出しs
置換文字列でs
捕捉グループの一致に対する "逆参照"とは対照的ですが)、興味深いことに基本的なPOSIX準拠のものです)。 \n
や\t
ような制御文字のエスケープシーケンス:
regexes (行選択のパターンとs
関数の最初の引数の両方)では、 \n
だけがエスケープシーケンスとして認識されると仮定します(通常、パターンスペースは\n
を終了せずに1行です)。ではなく、文字クラス内の、例えば、そのよう[^\n]
動作しません。(あなたの入力は何の制御文字が含まれていない場合以外。 \t
、あなたがエミュレートすることができます[^\n]
と[[:print:][:blank:]]
いずれかで、一般的に、 リテラルとして制御文字が含まれるスプライスさ-にANSI C-引用符で囲まれた文字列 (例えば、経由 - [2]) リテラルとしてそれ以外の場合は、スプライス制御文字で; $'\t'
中)それをサポートするシェル( bash,
ksh、 zsh
)、またはprintf
(例えば"$(printf '\t')"
) を使用したコマンド置換を介して実行できます。
sed 's/\t/-/' <<<$'a\tb' # -> 'a-b'
sed 's/'$'\t''/-/' <<<$'a\tb' # ANSI C-quoted string
sed 's/'"$(printf '\t')"'/-/' <<<$'a\tb' # command subst. with printf
s
コマンドで使用される置換文字列では、 制御文字のエスケープ・シーケンスはサポートされていないため、制御文字も含めてください。 リテラルとして、上記のように。
sed 's/-/\t/' <<<$'ab' # -> 'a<tab>b'
sed 's/-/'$'\t''/' <<<'a-b'
sed 's/-/'"$(printf '\t')"'/' <<<'a-b'
同上にテキスト引数の i
と機能 : 制御文字列を使用していません -以下を参照してください。 a
ラベルと分岐 :ラベルとb
とt
関数のlabel-name 引数には、 リテラル改行またはスプライスされた$'\n'
いずれかが続く必要があります 。または、複数の-e
オプションを使用して、ラベル名の後ろの各行を終了することもできます。
sed -n '/a/ bLBL; d; :LBL p' <<<$'a\nb' # -> 'a'
sed -n '/a/ bLBL d; :LBL p' <<<$'a\nb'
$\n
インスタンス): sed -n '/a/ bLBL'$'\n''d; :LBL'$'\n''p' <<<$'a\nb'
-e
オプション): sed -n -e '/a/ bLBL' -e 'd; :LBL' -e 'p' <<<$'a\nb'
テキストを挿入/追加a
ための関数i
とa
:テキスト引数を指定する前に、関数名の後に\
、 リテラル改行またはスプライスイン$'\n'
いずれかを続けます。
sed '1 i new first line' <<<$'a\nb' # -> 'new first line<nl>a<nl>b'
sed -e '1 i\'$'\n''new first line' <<<$'a\nb'
-e
ないと、テキスト引数は、macOS(バグ?)の出力では改行で終了するのは不可能です。 \n
や\t
などの制御文字エスケープを使用しないでください 。これはLinuxでのみサポートされているからです。 \
それらを-escape。 -e
オプションを続ける必要があります(これは全バージョンに適用される一般的な要件です) 。 関数リスト ( {...}
囲まれた複数の関数呼び出し)の中で、 最後の関数を閉じる前に必ず終了してください}
;
。
sed -n '1 {p;q}' <<<$'a\nb' # -> 'a'
sed -n '1 {p;q;}' <<<$'a\nb'
GNU sed
特有の機能がBSD sed
から完全になくなった:
両方のプラットフォームをサポートする必要がある場合は、あなたが逃してしまうGNUの機能:
さまざまな正規表現マッチングと置換のオプション (行選択のパターンとs
関数の最初の引数の両方):
I
オプション(信じられないほど、BSD sed
はこれをまったくサポートしていません)。 M
オプション( ^
/ $
は各行の開始/終了と一致します ) s
機能を参照してくださいhttps://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Commandを エスケープシーケンス
substring操作を可能にするs///
関数s///
置換引数の\u
などの置換に関連するエスケープシーケンス。例: sed 's/^./\u&/' <<<'dog' # -> 'Dog'
- http://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022を参照してください。 -コマンド
制御文字のエスケープシーケンス: \n
、 \t
、...、コードポイントに基づくエスケープに加えて。たとえば、次のすべてのエスケープ(16進数、8進数、10進数)は一重引用符( '
)を表します: \x27
、 \o047
、 \d039
- https://www.gnu.org/software/sed/manual/ sed.html#エスケープ
以下のようなアドレス拡張 、 first~step
ステップごと番目の行にマッチする、 addr, +N
次Nラインを一致させるaddr
、... -参照http://www.gnu.org/software/sed/manual/sedを。 html#アドレス
[1] macOS sed
バージョンは、FreeBSDやPC-BSDのような他のBSDのようなシステムのバージョンより古いです。残念ながら、これは、例えば、FreeBSDで動作する機能がmacOS上で動作するとは想定できないことを意味します。
[2] ANSI Cで引用された文字列$'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'
は\n
(およびNUL)以外のすべてのASCII制御文字が含まれているため、 [:print:]
[^\n]
かなり頑丈なエミュレーションのために:
'[[:print:]'$'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'']