0

これが私のサンプルリストです:

AAA BBB CCC1
DDD EEE FFF1
GGG HHH III1           <----- I want to remove this
GGG HHH III3 >>updated <----- I want to keep this
JJJ KKK LLL7

For ループを使用してリストをトラバースしているので、">>updated" が含まれるすべての行に注目し、1 行前に戻って古い行 (更新されていない) を削除してから、次の行に進みたいと考えています。 ">>updated" 行の次の行。したがって、基本的に私の最終的な出力は次のようになります。

AAA BBB CCC1
DDD EEE FFF1
GGG HHH III3
JJJ KKK LLL7

シェルスクリプトから他のフィールドの値を解析するために awk を使用していますが、この前後の手順を実行する方法がよくわかりません。どんな助けでも大歓迎です。

4

5 に答える 5

4

これはうまくいくかもしれません(GNU sed):

sed -r '$!N;s/.*\n(.*)\s+>>updated\s*$/\1/;P;D' file

パターン スペースに 2 行を保持し、最後の行が要件に一致したら最初の行を削除します。

awk ソリューションは次のようになります。

awk 'sub(/ *>>updated.*/,""){l=$0;next};NR>1{print l};{l=$0};END{print l}' file
于 2013-05-03T10:08:17.887 に答える
3

tac素晴らしいですが、すべてのディストリビューションのデフォルトではありません。利用できない場合は、 awk 単一プロセスのワンライナーを次に示します。

awk -F' >>' 'p{if($2~/updated/){p=$1;next}print p}{p=$0}END{print p}' file
于 2013-05-03T11:02:09.657 に答える
1

最も簡単な方法は、入力ファイルに行の配列を作成しますが、>>updated が存在しない場合にのみ配列インデックスを増やして、>>updated を含む行が配列内の前のエントリを上書きし、内容を出力することです。ファイルの最後に到達したときの配列の:

$ cat file
AAA BBB CCC1
DDD EEE FFF1
GGG HHH III1           <----- I want to remove this
GGG HHH III3 >>updated <----- I want to keep this
JJJ KKK LLL7

$ awk '!/>>updated/{++numLines} {line[numLines]=$0} END {for (nr=1;nr<=numLines;nr++) print line[nr]}' file
AAA BBB CCC1
DDD EEE FFF1
GGG HHH III3 >>updated <----- I want to keep this
JJJ KKK LLL7

その行の >>updated 以降のテキストを削除したい場合は、その存在のテストを、それを削除しようとするテストに変更できます。

$ awk '!sub(/ *>>updated.*/,""){++numLines} {line[numLines]=$0} END{for (nr=1;nr<=numLines;nr++) print line[nr]}' file
AAA BBB CCC1
DDD EEE FFF1
GGG HHH III3
JJJ KKK LLL7

>>updated が存在する場合、sub() はそれを削除して成功を返すので、>>updated が存在することがわかります。それ以外の場合、sub() は何もせずに失敗を返すため、>>updated が存在しないことがわかります。

于 2013-05-03T12:14:04.763 に答える