패턴 안의 텍스트와 관련하여 여러 줄의 패턴 사이에서 텍스트 삭제


0

그러나 블록 내에 특정 텍스트가 들어있는 경우에만 삭제해야하는 텍스트 블록이 있습니다.

...
<script language="JavaScript">
    var somethingA = 0;
    var somethingB = 0;
    var somethingC = 0;
    // do some stuff
</script>

<script language="JavaScript">
    var somethingA = 0;
    var somethingC = 0;
    var somethingD = 0;
    // do some stuff
</script>
....

나는 오직 그만 제거하고 싶다. <script> 그 블록 var somethingB 그 안에. 어떤 수의 <script> 어떤 위치에있는 파일의 블록들.

나는 sed와 같은 것을 사용하기를 바랬다.

sed 's/<script/,/<\/script>/ D'

그러나, 나는 단지 블록을 삭제하는 방법을 알아낼 수 없다. var somethingB 그 안에.

추신 : 나는 또한 perl이나 awk를 사용할 수있다. 나는 오히려 일관성을 위해서 sed를 사용하고 싶지만 perl이나 awk에서 더 쉬울 경우이 시점에서 기어를 꽤 빨리 전환 할 것입니다. 감사!



@glennjackman HTML이 아닌 척 해보자 ;-)
Matt

답변:


1

의 부분 해법이 vim 허용 가능 :

:%s/<script [^<]*\(\n[^<]*\)*somethingB.*\(\n[^<]*\)*<\/script>//g

그러나 내부에 다른 태그가있는 경우에는 작동하지 않습니다. <script> 사용하기 때문에 [^<]패턴에 포함되지 않을 수 있습니다. <.


0

나는 간단한 해결책이 없다. 실제로 그것은 awk를 사용하여 awk의 C와 유사한 언어로 필요한 알고리즘을 코딩합니다. 필터링 할 텍스트가 'filename'이라는 파일에 있다고 가정합니다.

awk 'BEGIN { curr=0 } \
     /<script .*>/ { in_block=1; del_block=0 } \
     /<\/script>/ { in_block=0; blockend=1 } \
     /var[[:space:]]+somethingB/ { if (in_block==1) \
                                     { del_block=1 } } \
    { if (in_block==0) \
        { if (blockend==0) \
            # Neither in a block nor block end reached.
            # Just print the line
            { print } \
          else \
            { # End of a block reached. Do block end handling
              # just this one time. Block end flag off
              blockend=0
              if (del_block==1) \
                { # delete the block. Just throw away the lines
                  # in the lines array
                  curr=0 } \
              else \
                { # End of block and no delete. Print it out
                  for (i=0; i<curr; i++) \
                    { print line[i] }
                    print   # Print the </script> line
                      # use line-array for the next block
                      curr=0 \
                } \
            } \
        } \
      else \
        { # In a block. Save the current line for later
          line[curr]=$0
          curr++ } \
    }' filename

에 대한 패턴 </script> (블록의 끝 마커)는 약간 간단합니다. 공백없이 정확하게 쓰여지기를 기대합니다. 공백을 포함 할 수 있다면 다음과 같이 작성할 수 있습니다.

/<[[:space:]]*\/script[[:space:]]*>/ 

에 대한 패턴 var somethingB ~이다. var - 하나 이상의 공백 - somethingB아마도 당신이 찾고있는 것일 것입니다. 사이에 정확히 하나의 공백으로 고정하려면 varsomethingB 간단 해. /var somethingB/


0

이 작업을 수행 할 수 있어야합니다. sed 직접. 내가 아니므로 sed 마법사, 두 번 달려와.

  1. 첫 번째 실행에서는 파일을 준비하여 <script>...</script> 블록은 공백 라인으로 둘러싸여 있습니다.

    sed -e '/<script/i\ ' -e '/script>/a\ ' code.js
    

    로켓트 과학이 아닙니다. i 삽입물 전에 패턴과 일치하는 라인, a 따라서 추가하다 패턴에 일치하는 선. 두 경우 모두 라인은 하나의 공백으로 만 구성됩니다.

    이것은 필요하다. sed 모든 블록을 별도로 감지합니다. 비 탐욕스러운 두 번째 단계에서).

  2. 두 번째 실행은 블록을 var somethingB 그 안에 :

    sed '/<script/,/script>/{H;d;};x;/var somethingB/d'
    
    • /<script/,/script>/{H;d;} 블록을 sed의 공간으로 옮긴다. H 공간을 확보하고, d 패턴 공간에서 삭제)
    • x 유지 공간을 패턴 공간과 교환한다
    • 패턴 인 경우 /var somethingB/ 일치하는 항목을 삭제합니다 ( d ) 전체를 보유하는 패턴 공간 <script> 블록.
    • 마침내 sed 암시 적으로 패턴 공간을 인쇄합니다.

      여기 내 참조는 유닉스 Sed 튜토리얼 .

  3. 그래서, 좋은 파이프를 가진 하나의 명령 행에서 :

    sed -e '/<script/i\ ' -e '/script>/a\ ' code.js | sed '/<script/,/script>/{H;d;};x;/var somethingB/d'
    

    원한다면 세 번째를 사용하십시오. sed 인스턴스를 사용하여 추가 빈 줄을 제거합니다.

    sed '/^ $/d'
    

@Matt : 내 sed 접근 방식에 만족한다면 피드백을 주시겠습니까?!
mpy

이 솔루션은 대단합니다! 웬일인지 나는 그것을 나의 편지함에서 놓쳤고, 지금까지 그것을 결코 보지 않았다. 유일한 단점은 파일의 마지막 줄을 제거한다는 것입니다. 하지만 그렇지 않으면 완벽하게 작동합니다.
Matt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.