パターン空間とホールド空間を用いたsed性能

パターン空間とホールド空間を用いたsed性能

425Mテキストファイルが与えられると、内容は次のようになります。

--START--
Data=asdfasdf
Device=B
Lorem=Ipsum
--END--
--START--
Data=asdfasdf
Lorem=Ipsum
Device=A
--END--
--START--
Device=B
Data=asdfasdf
--END--
...

作業は、(と含む)の間のすべての内容をsed印刷することです。 2つのソリューションが提供されます--START----END--Device=Aここそしてここ。 2 つのコマンド間で実行時間の差が大きくなります。 2番目のコマンドは非常に高速ですが、どのように動作するかについてさらに説明が必要ですか?

$ sed -n '/--START--/{:a;N;/--END--/!ba; /Device=A/p}' file
$ sed 'H;/--START--/h;/--END--/!d;x;/Device=A/!d' file

最初のコマンドの説明:

仕組み:

/--START--/{...}含まれている行に達するたびに、中--START--括弧内のコマンドが実行されます{...}

:a;ラベル「a」を定義します。

N;次の行を読み、パターンスペースに追加してください。

/--END--/!baパターンスペースに現在のラベルが含まれていない場合は、--END--ラベルに戻りますa

/Device=A/pここまで来るとパターン空間がで始まり--START--で終わるという意味です--END--。さらに、パターンスペースにそれが含まれている場合はDevice=A、それを印刷しpてください。

2番目のコマンドの説明:

sed 'H              #add line to hold space
     /--START--/h   #put START into hold space (substitute holded in)
     /--END--/!d    #clean pattern space (start next line) if not END
     x              #put hold space into pattern space
     /Device=A/!d   #clean pattern space if it have not "Device=A"
    ' file

答え1

心に留めておくべきことの一つは、正規表現の一致が「費用がかかります」ということです。したがって、パターンバッファにエントリが多いほど、検索速度が遅くなります。
この特別なケースでは、sed3つのパターンを見つける必要があります(1、2、3で番号を付けます):範囲START(1)、範囲END(2)、およびその範囲内のMATCH(3)(存在する場合)。

両方の解決策の主な違いは、範囲内のすべての行を格納するために使用されるバッファです。これは、範囲の終わりを検出する方法を決定します。

最初の解決策は各行でSTART(1)を検索するように機能します。これを見つけると、パターン空間に行を追加し始め、各反復ごとにEND(2)の範囲を確認する必要があります(毎回新しいデータ行を追加する)。一度にパターン空間でバッファ全体を再検索します。ENDを入力すると、いつ停止するかを知ることができます。)一度見つけたら、全パターン空間から MATCH(3) を検索します。

2番目のソリューションは異なる動作をします。つまり、予約済みスペースに行を無条件に累積して、1行あたりH2つのパターンマッチング(START(1)とEND(2))を実行して、それぞれの範囲を決定します。これはとても速い。範囲の終わりを検出すると、xバッファーが変更されます(パターンスペースには、予約済みスペースに累積されたすべての行が含まれます)。MATCH(3) の全パターン空間検索

ご覧のとおり(3)はまったく同じどちらの場合も、両方のスクリプトがsedMATCH検索を実行します。パターン空間にSTARTからENDまでのすべての行が含まれている場合。したがって、2つのソリューションを区別することはMATCH検索ではありません。ここでの主な違いは(2)によって発生します。
2番目のソリューションは、各行でENDを検索します。行にENDが含まれていない場合は、dパターン空間からそれを削除してループを再開します。つまり、別の行を取得してから、もう一度、ENDなどを見つけようとします。 ENDが見つかる前に、パターン空間に1行以上はありません。
これとは対照的に、最初の解決策は、a;N;/--END--/!ba 前の実行との違いが1行だけで構成されていても、ますます大きなテキストバッファで実行され続けます。大容量のテキストファイルを扱う場合、これは決して良いことではありません。 START-ENDの範囲が数千行に及ぶと想像してください。

つまり、検索範囲が終了すると作業速度が遅くなる。


第1の技術が第2の技術と比較してどれだけ遅いかについての良い例は、ここで見つけることができる。

リストを区切り文字を使用して1行に変換

私のテストからわかるように、最初のソリューションはテストを完了できませんでした。

関連情報