Mac OSX上のsedと他の「標準」sedの違いは?


61

sedコマンドに関するこの質問に対してこのサイトで提供されている回答を使用して、空白行を他の2行のコンテンツに置き換えるいくつかの問題があり、Mac OSのsedコマンド(10.6.7 ) 異なります。私はそれがそうだとは思いませんが、このサイトの他の人が違う考えをしたのではないかと思っていました。

回答:


43

シェルユーティリティの動作は、unixの亜種間で若干の違いがあります。複雑な歴史を持つ多くのUNIXバリアントがあります。POSIX標準やそのスーパーセットSingle UNIX仕様などの標準化の取り組みがあります。現在、ほとんどのシステムはPOSIX:2001(Single UNIX Specification version 3とも呼ばれます)を実装していますが、わずかな違いと多くの拡張機能があります。Single Unixの仕様はチュートリアルではありませんが、コマンドが何をしているのか既にわかっている場合はバージョン3を読むことができます。いくつかの機能が標準か特定のシステムの拡張かを知るためにそれを調べることができます。

UNIXユーザーの大半はLinuxを使用しており、他のバリアントは使用していません。LinuxにはGNUユーティリティが付属しており、GNUユーティリティには多くの場合、標準に対する多くの拡張機能があります。そのため、Linuxでは機能するが、他の大学では機能しないコードが非常に多くあります。これらの拡張機能に依存しているためです。

sedについては、すべてのシステムがサポートする最低限のsed Single Unix仕様、実装がサポートするものについてはシステムのmanページ、ほとんどの人が使用するGNU sedマニュアル参照してください

GNU sedの非標準の拡張機能の1つは、複数のコマンドを同時に実行できるようにすることです。たとえば、このGNU sedプログラムはa、を含むすべての行を出力しますが、最初に変更bcます。

sed -ne '/a/ {s/b/c/g; p}'

{また}、実際には個別のコマンドであるため、完全な移植性を確保するために、個別の行(ファイル内)または個別の-e引数(コマンド行)で指定する必要があります。後のコマンド区切り記号の欠如とコマンド区切り記号として{の使用は;、一般的な拡張機能です。以前}はコマンド区切り文字がなかったため、あまり一般的ではありません。これは標準に準拠しています。

sed -n -e '/a/ {' -e 's/b/c/g' -e p -e '}'

これは非標準ですが、一般的に受け入れられています。

sed -ne '/a/ { s/b/c/g; p; }'

別の非標準ですが一般的な拡張機能は、置換テキストの\n改行を意味するsための使用です(正規表現での使用は標準です)。移植可能な方法は、sedスクリプトにバックスラッシュと改行を含めることです。別の一般的な拡張子は\+\?あり\|、正規表現では1つ以上、最大で1つ、および交互を意味します。移植性のある基本的な正規表現にはこれらはありません。たとえば、最初のコマンドは、空白の連続したシーケンスを改行で置き換える移植性のない方法です。2番目のコマンドは、標準に準拠したコマンドです。

sed -e 's/ \+/\n/'
sed -e 's/  */\
/'

GNU拡張機能に関するすべてのケースで、非標準的な使用法であることに注意してください。GNU sed自体は、標準で許可されている(ただし、必須ではなく、指定されていない)ことを行うため、準拠しています。準拠していない場合やPOSIXLY_CORRECT、環境で実行すると役立つ場合があります。それと同様に、s/[\n]//gバックラッシュとn文字を削除する必要がありますが、代わりに改行を削除します。または、N最後の行のコマンドの動作。
ステファンシャゼラス

sed -ne '/a/ { s/b/c/g; p; }'2016年版の標準以来、標準です。常にポータブルでした。参照してくださいaustingroupbugs.net/view.php?id=944&nbn=7
ステファンChazelas

60

OS Xには現在、2005年以降のFreeBSD sedが付属しています。以下の違いのほとんどは、他のBSD sedバージョンにも適用されます。

OS Xのsedは-EEREとGNU sedを使用し-rます。GNU sedの-Eエイリアスです-r(4.2で追加され、4.3まで文書化されていません)。FreeBSDとNetBSD sedの新しいバージョンは、-Eとの両方をサポートしてい-rます。OpenBSD sedはのみをサポートします-E

-i ''OS Xのsedで動作しますが、GNU sedでは動作しません。-iGNU sed、NetBSDの最近のバージョン、OpenBSDで動作しますが、sedOS Xのsedでは動作しません。-i -e両方で動作しますsedが、FreeBSDの場合-e、ファイル名に追加された元のファイルのバックアップを作成します(そして、複数の式をに渡す必要はありませんsed)。

GNU sedの解釈は次のようにシーケンスエスケープ\t\n\001\x01\w、とします\b。OS XのsedおよびPOSIX sedは解釈のみを行います\n(ただし、の置換部分は除きsます)。

GNU sedの解釈\|\+および\?BREではなく、OS XのSEDとPOSIXのsedはありません。\(\)\{、および\}POSIX BREです。

GNU sedでは;、前に省略や改行を使用できます}が、OS Xのsedではできません。

i(挿入)、a(追加)、およびc(変更)の後に、OS XのsedおよびPOSIX sedではバックスラッシュと改行が必要ですが、GNU sedではそうではありません。GNUのSEDは、によって挿入されたテキストの後に行方不明に改行を追加してiaまたはcが、OS Xのは、sedをしません。たとえば、sed 1iaはGNUの代替sed $'1i\\\na\n'です。

たとえばprintf a|sed -n p、OS Xのsedに改行を追加しますが、GNU sedには追加しません。

OS Xのsedは、I(大文字と小文字を区別しない)またはM(複数行)修飾子をサポートしていません。FreeBSD sedサポートの新しいバージョンI

sedのOS Xはサポートしていません-s--separate)、 (-u)、--unbufferedまたは-z--null-data)を。

GNU sedでサポートされていないBSDオプションの1つは-awファイルを切り捨てる代わりにファイルに追加することです。

OS Xのsedで動作しないGNU sedコマンドの例:

sed /pattern/,+2d # like `sed '/pattern/{N;N;d;}'`
sed -n 0~3p # like `awk NR%3==0`
sed /pattern/Q # like `awk '/pattern/{exit}1'` or `sed -n '/pattern/,$!p'`
sed 's/\b./\u&/g' # \u converts the next character to uppercase
sed 's/^./\l&/' # \l converts the next character to lowercase
sed -i '1ecat file_to_prepend' file # e executes a shell command
sed -n l0 # 0 disables wrapping

4
-i -eOSXでは動作しません。-e接尾辞としてはまります。
クリスマーティン

3
@ChrisMartinはい、OS Xバージョン-iでは、空の文字列であっても常に接尾辞が必要です。動作する-i '' -eはずです。
ウォルディリアス16

@waldyrious OSXでのみ動作します。
クリスマーティン

はい、それはそのバージョンの癖です:)
waldyrious

3
文は「-i -e両方で動作します。」あなたの答えでは、クロスプラットフォームソリューションがあることを示唆しています。どうやらありません。
レオンデペオン

5

LinuxとMacの両方で同じスクリプトが動作することがわかった最良の方法は、次のとおりです。

sed -i.bak -e 's/foo/bar/' -- "${TARGET}" &&
  rm -- "${TARGET}.bak"

またはperl、それ-iがどこから来たかを使用します。perl -Tpi -e 's/foo/bar/' -- "$TARGET"
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.