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


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아마도 당신이 찾고있는 것일 것입니다. 사이에 정확히 하나의 공백으로 고정하려면 var 과 somethingB 간단 해. /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.