ブロックのアドレスの後にsedコマンドをグループ化できないのはなぜですか?

ブロックのアドレスの後にsedコマンドをグループ化できないのはなぜですか?

sed特定のパターンを除くすべての行を印刷しようとしています。以下がうまくいかない理由を理解できません。

sed '/PATTERN/{d;q}' file

sedスクリプトについて私が理解したところによると、この式の結果は次のようになります。

  • 行が一致すると、/PATTERN/コマンドで構成されたグループを実行します。
    1. dパターンスペースの削除(=現在行)
    2. quit はその後、現在のパターン空間を印刷します。

孤立した状態で、2つの/PATTERN/d操作/PATTERN/q、つまりd問題のある行が削除され終了しますqsedしかし、ラインを印刷した後、文書化されているように。しかし、これら2つの操作をブロックに結合するとq無視されるようです。

Q代わりにGNU拡張として使用できることを知っていますが{d;q}(これは期待どおりに機能します!)、上記の内容がうまくいかない理由とドキュメントをどのように誤解したかを理解したいと思います。


私の実際のユースケースは、ファイルの最初の行が実際にパターンと一致し(いくつかの代替操作を実行した後)スキップするため(少し)複雑です。

sed -e '1{s/>21/>chr21/; n}' -e '/>/{d;q}' in.fasta >out.fasta

ただし、上記の単純化されたケースは同じ動作を示しています。

答え1

特定のパターンが一致するまでファイルのすべての行を出力します。いいえ一致する行を出力するには、次のように使用できます。

sed -n '/PATTERN/q; p;' file

ここで、パターン空間のデフォルト出力は各サイクルの終わりに無効になります-n。代わりに各行を明示的に印刷しますp。指定されたパターンが一致すると処理を停止しますq

21fastaファイルの最初の行で染色体21の名前を変更し、chr21次のfastaヘッダー行に達するまでその染色体のDNAを抽出し続ける実際のより長いコマンドは、次のように書くことができます。

sed -n -e '1 { s/^>21/>chr21/p; d; }' \
       -e '/^>/q' \
       -e p <in.fasta >out.fasta

または

sed -n '1 { s/^>21/>chr21/p; d; }; /^>/q; p' <in.fasta >out.fasta

元の式の問題は、d新しいループを開始することです(つまり、次の行を強制的にパターン空間に読み込み、スクリプトの先頭にジャンプします)。これはq決して実行されないことを意味します。

GNU以外のシステムで構文を正確にするには、元のスクリプトは次のようになります/PATTERN/ { d; q; };後に追加される内容に注意してくださいq(スペースは重要ではありません)。

答え2

dパターンスペースのみを削除しないでください:fromPOSIX仕様

[2addr]d

パターンスペースを削除して次のサイクルの開始

(私の強調)

このqコマンドにはアクセスできません。

答え3

二重アドレス形式を使用して同じ出力を取得できます(最初のアドレスのみがその前の行と一致します)。

sed -e '/PATTERN/,$d'

ただし、使用されている方法とは異なり、qこれはsed各入力ラインを読み続けることを意味します。これは、大容量入力ファイルまたはパイプから読み取るときに影響を与える可能性があります。

関連情報