sedを使用してn番目のキーワードの後に​​行を追加するには?

sedを使用してn番目のキーワードの後に​​行を追加するには?

sedを使用してn番目の発生後にチェックを追加したいと思います。

入力する:

DCR
DCR
DCR

出力:

DCR
DCR
check
DCR

sedを使用できますか?

答え1

GNU sedを使用すると置き換えることができます。Naの目のパターンワイヤー

$ echo "foofoofoofoo" | sed 's/foo/&\nbar/2'
foofoo
barfoofoo

それ以外の場合Nパターンを含む3行目は、awkを使用すると簡単です。

awk -v n=2 -v patt=foo '{print} $0 ~ patt && ++count == n {print "bar"}' <<END
foo1
foo2
foo3
foo4
END
foo1
foo2
bar
foo3
foo4

答え2

GNU sedの使用:

sed -z 's/DCR/&\ncheck/2' <input >output

更新されていないバージョンの場合:

sed '/DCR/{p;s/.*/1/;H;g;/^\(\n1\)\{2\}$/s//check/p;d}' <input >output

DCR連続して1回以上発生する場合:

sed '
/DCR/{p
      x                               # tests if already have met pattern
      /^\(\n\a\)\{2\}/!{              #+apropriate times and, if so, cancel
        x                             #+the rest of commands
        s/DCR/\a/g                    # exchange DCR by \a symbol
        s/^[^\a]*\|[^\a]*$//g         # delete everything before & after it  
        s/[^\a]\+/\n/g                # substitute everything between by \n
        H
        g
        /^\(\n\a\)\{2\}/s/.*/check/p} # add 'check' for double pattern
      d}' <input >output

答え3

sedスタックでできます...

sed '/match$/N
     s/\n/&INSERT&/3;t
     $n;N;P;D'

それから挿入されますINSERT3時ごと非順次起こったmatch入力中。これはsed、他のすべての行を保存しようとしないので、私が知っている最も効率的な方法です。matchesまた、バッファの交換や逆参照の比較は必要ありませんが、sed単に行番号を行期間だけ増やす唯一の計算方法です。

もちろん、これによりわずかなオーバーヘッドが追加されます。つまり、一致する各パターン空間はやや大きくなりますが、まだ同じストリームであり、逆追跡はありません。ただ先入選出- 非常に適切なアプローチだと思いますsed。実際に戻って一致を確認するのではなく、次のことがsedできます。さらに進むすべてのゲーム。少し誇りに思っています。なぜ以前はそんな考えを一度もやったことがないのかわかりません。

ただし、上記のバージョンは入力後1行しか機能しないため、繰り返しを多少圧縮します。解決策は、さらに一歩進んで電流の流れを維持するために、ループ内に牧場のアベル短絡ループを設定するための追加の複雑b:lが必要です。N;P;D

仕組みは次のとおりです。

seq 100000| sed -ne':n
            s/\n/&\tCheck&\t/5p;t
            N;/0000$/bn'  -eD

...私には印刷家...

49995
49996
49997
49998
49999
    Check
    50000
99995
99996
99997
99998
99999
    Check
    100000

カウントを維持するために発生するたびにラインバッファを増やします。matchそして、パターン空間のスライドウィンドウに別の線を固定します。これにより、一致が見つかったことを確認するために必要なすべての作業は、交換を試みることです。s///nth \nパターン空間の行文字。もしかしたら私たちは会いましたかn matchesこれまで、testは現在の反復から分岐して増分を完全に消去できます。

上記の例では、バッファは文字列で終わる各パターン空間に対して一度だけ増加します。0000。そのうちの5つが見つかったら、sed現在のパターンスペースとバッファ全体を印刷してカウンタを消去します。

あなたのため:

printf DCR\\n| tee - - - - - |
sed -e:n -e's/\n/&\tCheck&\t/2;t
     $n;    N;/DCR$/bn' -eP\;D

DCR
DCR
    Check
    DCR
DCR
DCR
    Check
    DCR

今表示したい場合ただこれnthそれは非常に簡単です。

printf DCR\\n        |
tee - - - - - - - - -|
sed -e:n -e's/\n/&\tCheck&\t/3;te
     $n;  N;/DCR$/bn' -e'P;D;:e
     n;be'

...詳しく見ると、表面だけが傷ついただけであることがわかります。

DCR
DCR
DCR
    Check
    DCR
DCR
DCR
DCR
DCR
DCR
DCR

答え4

GNU sed

sed仕事には適していませんが、もちろんまだできます。以下は、非常に長い文字列を予約済みスペースに保存し、それを使用して発生回数をn計算する方法です。DCR

n=2

((yes | head -n$n | tr -d \\n; echo); cat infile) | 
sed '
  1 {h;d}            # save counting string
  /DCR/ {            #
    x; s/.//; x      # n--
    T chk            # if n=0 goto "chk"
  }
  P;D 
  :chk               # insert check
  i\check
  :a; N; ba          # print rest of file
'

アッ

指摘したとおりグレン、awkはよりきれいです。ここにゴルフ版がありますが、同様のロジックがあります。

<infile awk '!n { print "check" } /DCR/ { n-- } 1' n=2

関連情報