次のファイルをインポートします。
$ cat f1
stu vwx yza
uvw xyz abc
abc def ghi
def ghi jkl
ghi jkl mno
jkl mno pqr
mno pqr stu
pqr stu vwx
stu vwx yza
最初の行から始めて、以下を含むabc
すべての行を印刷します。最初mno
GNUが含まれますsed
:
$ sed -n '/abc/,/mno/p' f1
uvw xyz abc
abc def ghi
def ghi jkl
ghi jkl mno
次回まですべての行を印刷するにはどうすればよいですか?最後のものContains mno
、たとえば、次の結果をどのように取得できますか?
uvw xyz abc
abc def ghi
def ghi jkl
ghi jkl mno
jkl mno pqr
mno pqr stu
つまり、GNUsed
の範囲選択を貪欲にする方法はありますか?
修正する
私の設定では:
- 欠落している場合は、
mno
ファイルの最後まですべての内容を印刷する必要があります。 mno
最初の以前は発生できませんabc
。- 常に1つ以上があり、同じ行には決してありません
abc
。abc
mno
編集するstu vwx yza
ファイルを含む行で始まらないように、最初にダミー行を追加しました。 (abc
最初の行から始まるソリューションを避けるために、ファイルは含まれているabc
最初の行から始める必要があります。)
答え1
sed '/abc/,$!d;0,/mno/b;:1;/mno/b;$d;N;b1' file
動作アルゴリズム:
2つのアドレス範囲を使用します。
最初は、/abc/,$!d;
最初のパターンマッチングの前にすべてを削除します。
2番目は、0,/mno/b;
パターンが一致するまで各ラインバッファ(パターンスペース)を送信し、残りのスクリプトの/mno/
出力をバイパスし、パターンがファイルに見つからない場合は削除を防ぎます。
残りのスクリプトは:1;/mno/b;$d;N;b1
ループで動作します。エディタバッファでは、パターンマッチが発生するまで行が追加されます。パターンが見つかると、/mno/
スクリプトの残りの部分をバイパスし、バッファ全体が出力に送信されます。一致するものがない場合は、バッファの最後の行を削除します。
答え2
awk
可能であれば使用してください。パターンが始まる行とパターンが停止する行を表示し、ファイルの1パスでその行を印刷できます(abc
最初の行から始めて最後の行までの行をバッファに保存することを含む)。
awk '/abc/ && !start {
start = NR
}
/mno/ {
stop = NR
}
start { line[NR] = $0 }
END {
if ( !stop ) {
stop = NR
}
for ( s = start; s <= stop; s++ )
print line[s]
}' file
開始パターンがない場合、動作せず、一連の空白行のみが印刷されます。
答え3
awk
バッファリングが少ない別の解決策:
awk '!f&&/abc/{f=1} f==1; f==2{buf=buf $0 ORS} f&&/mno/{f=2; printf "%s",buf; buf=""}' input.txt
- これにより、最初の項目
abc
(フラグを1に設定)からf
始まり、最初の項目まですべての内容が印刷されますmno
。f==1
ルールブロックの外側のステートメントは、に設定されるたびに現在の行をawk
印刷する必要があることを示します。f
1
- その後、各発生後
mno
(f
現在値2)、すべての行の内容がバッファに保存されbuf
、次の発生時に印刷され消去されますmno
。最初にmno
発生した状況に正しく対応していることを確認してください。今後まず、このロジックを適用する前に少なくとも1に設定する必要がありますabc
。f
mno
したがって、2つの出現の間、または最後の出現とmno
ファイルの終わりの間に最大テキストを保存します(後者の部分は印刷されません)。
速度のためにメモリ効率を変えたい場合、次の2段階のアプローチはバッファリングにまったく依存しません。
awk 'FNR==NR{if (/abc/&&!start) {start=FNR} else if (/mno/) {end=FNR}; next} FNR>=start&&(!end||FNR<=end)' input.txt input.txt
その後、ファイルは2回処理されます(したがって、パラメータとして2回指定されます)。
- 最初に
FNR
各ファイルのラインカウンタがグローバルラインカウンタと同じ場合、最初の発生と最後の発生を見つけて、対応する行NR
番号をそれぞれに保存します。abc
mno
start
end
- 2番目のパスでは、カウンタがend
FNR
の間に含まれるたびに(またはunset以上の場合)行を印刷します。start
end
start
end
答え4
abc
予約済みスペース内の行から始めてすべての行を収集し、強欲属性を使用して.*
最後の行以降のすべての行を削除できますmno
。
sed '/abc/,$!d;H;$!d;x;s/\n//;s/\(.*mno[^\n]*\).*/\1/'
/abc/,$!d
最初の行の前にあるすべての項目(または行がまったくない場合はファイル全体)をd
削除することです。abc
abc
H;$!d
予約済みスペースにファイル全体を収集するクラシックモード。 (非常に大きなファイルの場合は問題になる可能性があります。)- 大きなバッファコピーを避けるために
x
使用する代わりにバッファを変更します。g
s/\n//
空の予約スペースに追加して、生成された誤った開始改行を削除します。s/\(.*mno[^\n]*\n\).*/\1/
その後すべて削除最後mno
行(または行がない場合は、要求時に残りのファイル全体を印刷しますmno
)。これは[^\n]
POSIXではなく、GNUなどの特定のバージョンでのみ機能しますsed
。