この質問へのコメントで、さまざまなsed実装がかなり単純なプログラムで同意しない場合があり、私たち(または少なくとも私)は、仕様が実際にそれに対して必要とするものを決定できませんでした。
問題は、削除された行から始まる範囲の動作です:
1d;1,2d
そのコマンドに到達する前に範囲の開始が削除された場合でも、行2を削除する必要がありますか?私の当初の期待はBSD sedに沿って「いいえ」でしたが、GNU sedは「はい」と言っており、仕様テキストをチェックしても問題は完全には解決しません。
私の予想に一致するのは、(少なくとも)macOSとSolaris sed
、およびBSD sed
です。反対は(少なくとも)GNUとBusybox sed
であり、多くの人々がここにいます。最初の2つはSUS認定で、他の2つはより普及している可能性があります。どの動作が正しいですか?
2アドレス範囲の仕様書には次のように記載されています。
sedのコマンドは、次のサイクルが終了しますかを開始するまでのユーティリティはその後、順番にそのアドレスがそのパターンスペースを選択するすべてのコマンドを適用しなければなりません。
そして
2つのアドレスを持つ編集コマンドは、最初のアドレスに一致する最初のパターンスペースから2番目のアドレスに一致する次のパターンスペースまでの包括的な範囲を選択します。[...]選択した範囲に続く最初の行から開始して、sedは最初のアドレスを再度探します。その後、プロセスが繰り返されます。
おそらく、ライン2がある 範囲内にかかわらず開始点が削除されたかどうかの、「第二に一致する次のパターン空間を介して第1のアドレスと一致する第1のパターン領域からの包含範囲」。一方、私は最初d
が次のサイクルに移動し、範囲に開始する機会を与えないことを期待していました。UNIX™認定の実装は、私が期待したことを実行しますが、仕様で要求されていることを潜在的に実行しません。
いくつかの実例となる実験が続きますが、重要な問題は、削除された行で範囲が始まるときに何をすべき sed
かです。
実験と例
問題の簡単なデモンストレーションはこれです。これは、行を削除するのではなく、余分なコピーを印刷します。
printf 'a\nb\n' | sed -e '1d;1,2p'
これは、提供するsed
入力の2行、a
およびb
。プログラムは2つのことを行います。
で最初の行を削除し
1d
ます。d
コマンド意志パターンスペースを削除し、次のサイクルを開始します。そして
- 各行が受け取る自動印刷に加えて、1から2までの行の範囲を選択して明示的に印刷します。したがって、範囲に含まれる行は2回表示されます。
私の期待は、これが印刷されることでした
b
ただ、1,2
1行目で到達できないため(d
次のサイクル/行に既にジャンプしているため)範囲a
が適用されず、範囲の包含は決して開始されず、削除されます。SolarisおよびBSDの一般的なsed
非POSIXと同様に、macOSおよびSolaris 10 の準拠するUnixがこの出力を生成します。sed
sed
一方、GNU sedは印刷します
b
b
範囲を解釈したことを示します。これはPOSIXモードでもそうでない場合でも発生します。Busyboxのsedは同じ動作をします(ただし、常に同じ動作とは限らないため、共有コードの結果ではないようです)。
さらなる実験
printf 'a\nb\nc\nd\ne\n' | sed -e '2d;2,/c/p'
printf 'a\nb\nc\nd\ne\n' | sed -e '2d;2,/d/p'
削除された行から始まる範囲を次の行から始まるかのように扱うように見えます。/c/
範囲を終了するために一致しないため、これは表示されます。を使用/b/
して範囲を開始すると、と同じように動作しません2
。
私が使用していた最初の実用的な例は
printf '%s\n' a b c d e | sed -e '1{/a/d;};1,//d'
/a/
最初の行にある場合でも、最初の一致までのすべての行を削除する方法として(GNU sedが使用0,/a/d
するもの-これはPOSIX互換の試みでした)。
代わりに、最初の行が一致する場合(または2番目の一致が/a/
ない場合はファイル全体)の2番目の一致まで削除することをお勧めします。これはもっともらしいと思われます-ただし、GNU sedのみがそれを行います。macOS sedとSolarisのsed製品の両方
b
c
d
e
私は予想通りそのため、(; Busyboxのは、単にプリントをsedのGNUは、終端されていない範囲を削除するから、空の出力を生成sedをd
し、e
どんな間違っ明確ではありませんこれは、)。一般的に、私は彼らが認定適合テストに合格したことは彼らの行動が正しいことを意味すると仮定しますが、十分な人々は私が確信していないことを示唆しており、仕様のテキストは完全に説得力がなく、テストスイートはできません完全に包括的です。
明らかに、矛盾を考慮して今日そのコードを書くことは実際には移植性がありませんが、理論的にはどこかで何らかの意味で同等でなければなりません。これはバグだと思いますが、どの実装に対して報告するのかわかりません。私の現在の見解では、GNUおよびBusybox sedの動作は仕様と矛盾していますが、それについて誤解される可能性があります。
ここでPOSIXには何が必要ですか?
ed
で処理し、sed
完全にバイパスしますか?