sedを使用して最初の行から最後のパターンを含む行まで印刷しますか?

sedを使用して最初の行から最後のパターンを含む行まで印刷しますか?

次のコマンドは、特定のパターンの最初のオカレンスまで印刷しますが、それ以降のオカレンスは含まないことを知っています。

sed -n '1,/<pattern>/p' <file>

sed '/<pattern>/q' <file>

たとえば、次の行を含むファイルがあるとします。

this is a cow   
this is a goat  
this is a some fish  
this is a fishie  
this is a fish  
this is a lion  
this is a cat

次のように出力します。

$ sed '/fish/q' file  

this is a cow  
this is a goat  
this is a some fish 

$ sed -n '1,/fish/p' file  

this is a cow  
this is a goat  
this is a some fish 

最初の行から最後の項目を含む行まで出力を開始したいと思います。つまり、私が望む出力は次のようになります。

this is a cow   
this is a goat  
this is a some fish  
this is a fishie  
this is a fish 

達成するために使用する方法は何ですかsed

答え1

この試み:

$ tac infile | sed -n '/fish/,$p' |tac

通常、sedコマンドで実行すると、最初の一致パターンから入力ファイルの終わりまですべての行が取得されます。

$ sed -n '/fish/,$p' file

this is a some fish
this is a fishie
this is a fish
this is a lion
this is a cat

だから私の解決策は次のとおりです。tac入力ファイルからコマンドを実行すると、最後に一致したパターンが最初のパターンに変わります。結果を見るtac infile

$ tac infile

this is a cat
this is a lion
this is a fish
this is a fishie
this is a some fish
this is a goat
this is a cow

このtacコマンドはコマンドと同じですcatが、tacファイルを逆順に印刷します。

最初のsedコマンドを実行すると、まず入力ファイルの最後までパターンに一致するすべての行が得られます。良い:

$ tac infile | sed -n '/fish/,$p'
this is a fish
this is a fishie
this is a some fish
this is a goat
this is a cow

さて。終わりました。tac行を元の順序に復元するには、コマンドを再実行するだけです。

$ tac infile | sed -n '/fish/,$p' |tac
this is a cow
this is a goat
this is a some fish
this is a fishie
this is a fish

完璧!

答え2

sedこれは非常に簡単です。 2つのバッファ間でわずかな調整が必要です。たとえば、

sed -n 'H;/fish/!d;$!n;x;p;G
' <<\INFILE
this is a cow
this is a goat
this is a some fish
this is a fishie
this is a fish
this is a lion
this is a cat
INFILE

このコマンドは、H挿入された行文字の後の既存のスペースに各行を追加します\n。一致し!ない行は出力から/fish/すぐに削除されます。これは私たちに線だけをd残します。/fish/したがって、この行はn入力された拡張行で上書きされます。その後、パターンとh既存のスペースが置き換えられます。H結局、私たちはラインを古いものにしました。これで、パターン空間はH前の空間であり、その逆も同様です。したがって、最後の行が一致したときに保存された内容をp印刷します。/fish/

p一致が見つかった場合にのみ印刷し、その間に中間行を保存するので、一致が最後に発生した場合にのみ到達します。ただし、一致する項目の間にできるだけ少ない量だけ保存します。xバッファが変更されるたびにフラッシュされます。結果は次のとおりです。

this is a cow   
this is a goat  
this is a some fish  
this is a fishie  
this is a fish

私が時々魚をスキップすることを伝えてくれたDon Christyに感謝します。これで、フラッシュするたびにバッファが両端にプッシュされ、現在のパターンスペースを削除する前に毎回上書きされます。それは最初と最後の行の魚と私が知っている限り、それらの間のすべての行に適用されます。

私がやっているもう一つのことは、n最後の行の延長コードを引くことです。これは絶対sed禁忌です。これを手伝ってくれたドンにもう一度感謝します。

より徹底した例:

sed 'x;/./G;//!x;/fish/p;//s/.*//;x;d'

これが他の問題をよりよく解決することを願っています。hパターン/既存のスペースはサイクルごとに変わります。これは、コマンドの最後に編集置換が追加されて空白行が発生するのをx防ぐためです。s///したがって、バッファが置き換えられ、バッファが空でないままになると、現在の行がここに追加され、その後に\newline文字が追加されます。それ以外の場合は、追加の行がバッファから出力されます。それ以外の場合、バッファは再び交換され、h前のスペースは現在のサイクル中は空のままになります。私が知る限り、このコマンドはすべての空白行と他のすべてを保持しますが、最後の一致で印刷を停止します。

私が経験した困難のいくつかは、通常、既存のhスペースで発生します。これを効果的に使用する唯一の方法は、既存のラインと比較するためにラインサイクルの下 - 後ろ - にあることです。私が普段好むのはloopingですN;P;D。おそらく、次のことを使ってこれを行うことができます。

sed -ne :n -e '/fish/!N;//p;//!bn'

入力拡張ラインをパターン空間に継続的にsed追加し、ラベルに戻って再試行します。Nb:n現在までに設定された行と一致しません。ラインサイクルの終わりに内容をダンプし、新しいバッファで再起動する前に、一致するラインまたはpラインシーケンスのみを印刷します。fish

ここでは、意図的に最後の行をテストしません。最後の行が一致すると印刷されます。それ以外の-n場合は、GNUの場合でも、sedループがファイルの最後の行をすべて終了するかどうかを決定します。

答え3

Sedより短いawkを使用することもできます。

awk ' /^fish/ { print $0 }' filename.txt

一部の人は次のように書くことができます:

awk ' /^fish/ { print $1 $2 $3 $4 $5 }' filename.txt

$n列を表します。ショートカットは$0行全体を表します。

答え4

Raku(以前のPerl_6)の使用

raku -e '$/.put if m/^ .* fish/ for lines.join("\n");'

入力例:

this is a cow   
this is a goat  
this is a some fish  
this is a fishie  
this is a fish  
this is a lion  
this is a cat

出力例:

this is a cow   
this is a goat  
this is a some fish  
this is a fishie  
this is a fish

上記の正規表現は1つの単語で終わり、その単語が行の最後の単語fishである限りfish正しく機能します。ただし、OPが全体をキャプチャしたい場合最後の行(例:fishermanフルワードを返す)上記の正規表現マッチングをに変更しますm/^ .* fish .*? $$ /

https://raku.org

関連情報