awk は一致前の行を除くすべての行を印刷します。

awk は一致前の行を除くすべての行を印刷します。

このファイルがあります。

john
robert
rose*
ann*
charles
david
liz*
louis
wendy*
kate*
mandy*
paul

「*」の前の行を除くすべての行を印刷したいので、必要な出力は次のようになります。

john
rose*
ann*
charles
liz*
wendy*
kate*
mandy*
paul

私は以前試しました:

awk '/\*/ {f=1}; (!f &&NR > 1) {print p}; {p=$0;f=0} END {print p}' file

出力を生成します

john
ann*
charles
liz*
mandy*
paul

コードに問題がありますか?

答え1

rose**()前の行なann*ので、基準がI want to print all lines except those lines before '*'期待される出力と一致せず、コードが言うように実行されるようです。

*代わりに、含む行を含む行と除外するすべての行を印刷して、表示する予定の出力を取得するには、*次のようにします。

$ awk '(NR>1) && ((p ~ /\*/) || !/\*/){print p} {p=$0} END{print p}' file
john
rose*
ann*
charles
liz*
wendy*
kate*
mandy*
paul

答え2

これはほとんど私の個人的な楽しみのためです。

sed同じ問題を解決するためのコマンド:

sed -e 'N' -e '/[^*]$/P' -e '/[*]\n.*[*]$/P' -e '$!D' -e 's/.*\n//' file

これにより、編集バッファの入力に2行が残ります。次の行は、N挿入されたリテラル改行文字によって既存のデータと区別されたものを使用して編集バッファに追加されますsed

*バッファの終わりがない場合、バッファの最初の部分が印刷されますP。その後にアスタリスクのない行がある場合、これは出力行の内容です。

バッファに*リテラルと改行文字が含まれている場合(たとえば、バッファの最初の部分がで終わる*そして*バッファの最後に;があり、最初の部分はとして印刷されますP。これは、アスタリスクの付いた行が後にあってもアスタリスクのある行を出力することです。

Dバッファの最初の部分は、終わりに達しない場合は削除されます。さらに、このDコマンドはスクリプトが最初のコマンドから自動的に開始されるようにします(ただし、編集バッファ全体をクリアしたり、他の入力行を自動的に読み取ったりしませんd)。

最後のコマンドに達すると、最後の行が読み込まれ、s最後の2行はバッファにあります。ここで、最初の行はすでに印刷されている必要があります(または印刷されてはいけません)。したがって、残りの最後の行を印刷する前に、その行を削除する必要があります。

より短いバリエーション:

sed -e '$q' -e 'N' -e '/[^*]$/P' -e '/[*]\n.*[*]$/P' -e 'D' file

Dこれは、最後の無条件コマンドが編集バッファに残っている最後の2行目も切り取り、スクリプトの先頭$qで短縮される最後の反復を可能にし、最後の行を印刷した後にスクリプトが終了するという事実に依存します。

答え3

もしsed受け入れられるなら

sed '/\*$/!{$!N;//!P;D;}' file

:で終わらない行の場合は次の行を*読みN、まだ一致するものがない場合は最初の行を印刷します。D最初の行を削除してプロセスを繰り返します。

関連情報