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수행할 수 있습니다 .더 나아가모든 게임. 조금 자랑스럽습니다. 왜 전에는 그런 생각을 한 번도 해본 적이 없는지 모르겠습니다.

그러나 위 버전은 입력 후 한 줄만 작동하기 때문에 반복을 다소 압축합니다. 해결책은 한 단계 더 나아가 전류 흐름을 유지하기 위해 루프 내부에 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

관련 정보