web-dev-qa-db-ja.com

Mac OSXのsedと他の「標準」sedの違いは何ですか?

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

67
Peter Grill

シェルユーティリティの動作は、UNIXバリアント間で多少異なります。多くの nix バリアントがあり、 complexhistory があります。 [標準化への取り組み[〜#〜] posix [〜#〜] 標準とそのスーパーセット Single UNIX specification などがあります。今日のほとんどのシステムは、POSIX:2001( Single UNIX Specificationバージョン とも呼ばれます)を実装しています。シングルUnix仕様はチュートリアルではありませんが、コマンドが何をしているのかすでにわかっている場合は、バージョン3を読むことができます。あなたはそれを調べて、いくつかの機能が標準であるか、特定のシステムの拡張であるかを知ることができます。

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

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

GNU sedの非標準の拡張機能の1つは、同時に実行される複数のコマンドをサポートしています。たとえば、このGNU sedプログラムは、aを含むすべての行を出力しますが、bを変更します最初にcに:

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; }'

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

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

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

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

-i ''はOS Xのsedで機能しますが、GNU sedでは機能しません。-iはGNU sedで機能します。NetBSDの最新バージョン、OpenBSD sed、ただしOS Xのsedではありません。-i -eは両方で機能しますが、FreeBSDの場合はsedがファイル名に-eを追加して元のファイルのバックアップを作成します(そして、sedに渡す式は1つだけです)。

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 1iased $'1i\\\na\n'の代替GNUです。

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

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

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

GNU sedでサポートされていないBSDオプションの1つは-aです。これにより、wがファイルを切り捨てるのではなく、ファイルに追加されます。

GNU OS Xのsedで動作しない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
69
Lri

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

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