파일의 두 태그 사이에 있는 모든 내용을 어떻게 제거합니까?

파일의 두 태그 사이에 있는 모든 내용을 어떻게 제거합니까?

\{{[}텍스트 파일에 텍스트가 있고 문자열 자체를 포함하여 및 등의 문자열 사이에 있는 모든 내용을 제거하고 싶습니다 . {]}\}이 두 문자열할 수 있는다른 줄에 있고 같은 줄에 있습니다. 두 경우 모두, 존재하다시작 부분이 있는 줄 \{{[}, 그 앞의 텍스트가 삭제되는 것을 원하지 않습니다. 즉, 왼쪽의 텍스트 - 뒤의 텍스트도 마찬가지입니다 {]}\}.

예는 다음과 같습니다. 콘텐츠가 포함된 텍스트 파일이 제공됩니다.

Bla Bla bla bla \{{[} more bla bla
even more bla bla bla bla. 

A lot of stuff might be here.

Bla bla {]}\} finally done.

Nonetheless, the \{{[} show {]}\} goes on.

스크립트는 콘텐츠가 포함된 다른 텍스트 파일을 반환해야 합니다.

Bla Bla bla bla  finally done.

Nonetheless, the  goes on.

불행하게도 단순해 보이는 이 작업은 나에게 너무 어려웠다 sed. 나는 매우 행복하다어느표준 Linux 시스템에 아무것도 설치할 필요가 없는 한 모든 언어 솔루션(C 및 일부 Java가 이미 설치되어 있음).

답변1

그리고 perl:

perl -0777 -pe 's/\Q\{{[}\E.*?\Q{]}\}\E//gs'

전체 입력은 처리 전에 메모리에 로드됩니다.

\Qsomething\Esomething정규 표현식이 아닌 리터럴 문자열로 처리됩니다 .

일반 파일을 수정하려면 다음 -i옵션을 추가하세요.

perl -0777 -i -pe 's/\Q\{{[}\E.*?\Q{]}\}\E//gs' file.txt

GNU를 사용 awk하거나 다음 을 수행하십시오 mawk.

awk -v 'RS=\\\\\\{\\{\\[}|\\{\\]}\\\\}' -v ORS= NR%2

거기서 우리는 정의합니다기록 구분 기호시작 또는 끝 태그 중 하나로 사용됩니다( 정규 표현식은 여기에서만 지원됩니다 gawk) mawk. RS하지만 다시 정규식 연산자의 문자(백슬래시 {, , ) [와 백슬래시를 이스케이프해야 합니다. 왜냐하면 백슬래시는 인수( , ... -v와 같은 것에 사용됨 )에 특수하므로 백슬래시가 많이 있기 때문입니다.\n\b

그런 다음 우리가 해야 할 일은 다른 모든 레코드를 인쇄하는 것뿐입니다. 모든 홀수 레코드에 대해 NR%2(true)입니다 .1

두 솔루션 모두 태그가 일치하고 부품이 중첩되지 않은 것으로 가정합니다.

최신 버전의 GNU를 사용하여 파일을 수정하려면 1 옵션을 awk추가하세요 .-i /usr/share/awk/inplace.awk


^사용하지 마세요-i inplace현재 작업 디렉터리(as or)에서 확장 기능을 먼저 gawk로드 하려고 하면 누군가가 해당 디렉터리에 악성 코드를 심었을 수 있습니다. 시스템과 함께 제공되는 확장 프로그램 의 경로 는 다를 수 있습니다. 출력을 참조하세요.inplaceinplaceinplace.awkinplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

답변2

sed   -e:t -e'y/\n/ /;/\\{{\[}/!b'               \
      -e:N -e'/\\{{\[.*{\]}\\}/!N'               \
           -e's/\(\\{{\[}\).*\n/\1/;tN'          \
           -e'y/ /\n/;s/\\{{\[}/& /;ts'          \
      -e:s -e's/\(\[} [^ ]*\)\({\]}\\}\)/\1 \2/' \
      -ets -e's/..... [^ ]* .....//;s/ //g;bt'   \
<<""
#Bla Bla {]}\} bla bla \{{[} more bla bla
#even more bla bla bla bla. \{{[} 
#
#A lot of stuff might be here.
#hashes are for stupid syntax color only
#Bla bla {]}\} finally {]}\} done.
#
#Nonetheless, the \{{[} show {]}\} goes \{{[} show {]}\} on.

#Bla Bla {]}\} bla bla  finally {]}\} done.
#
#Nonetheless, the  goes  on.

그러나 더 좋은 방법이 있습니다. 대체 항목이 훨씬 적으며 .*항상 사용하는 것이 아니라 한 번에 몇 문자씩 사용합니다 . 실제로 .*이것이 사용되는 유일한 경우는 처음 발생하는 시작이 첫 번째 후속 끝과 확실히 쌍을 이루어 중간의 패턴 공간을 지울 때입니다. 나머지 시간에는 다음 구분 기호에 도달하기 위해 최대한 많이 삭제합니다 sed. D돈이 가르쳐줬어요.

sed -etD -e:t -e'/\\{{\[}/!b'  \
    -e's//\n /;h;D'       -e:D \
    -e'/^}/{H;x;s/\n.*\n.//;}' \
    -ett    -e's/{\]}\\}/\n}/' \
    -e'/\n/!{$!N;s//& /;}' -eD \
<<""
#Bla Bla {]}\} bla bla \{{[} more bla bla
#even more bla bla bla bla. \{{[} 
#
#A lot of stuff might be here.
#hashes are for stupid syntax color only
#Bla bla {]}\} finally {]}\} done.
#
#Nonetheless, the \{{[} show {]}\} goes \{{[} show {]}\} on.

#Bla Bla {]}\} bla bla  finally {]}\} done.
#
#Nonetheless, the  goes  on.

그러나 RHS \n개행 문자는 문자 그대로 백슬래시로 이스케이프된 개행 문자로 대체되어야 할 수도 있습니다.

보다 일반적인 버전은 다음과 같습니다.

#!/usr/bin/sed -f
####replace everything between START and END
   #branch to :Kil if a successful substitution
   #has already occurred. this can only happen
   #if pattern space has been Deleted earlier
    t Kil
   #set a Ret :label so we can come back here
   #when we've cleared a START -> END occurrence
   #and check for another if need be
    :Ret
   #if no START, don't
    /START/!b
   #sigh. there is one. get to work. replace it
   #with a newline followed by an S and save
   #a copy then Delete up to our S marker.
    s||\
S|
    h;D
   #set the :Kil label. we'll come back here from now
   #on until we've definitely got END at the head of
   #pattern space.
    :Kil
   #do we? 
    /^E/{
       #if so, we'll append it to our earlier save
       #and slice out everything between the two newlines
       #we've managed to insert at just the right points        
        H;x
        s|\nS.*\nE||
    }
   #if we did just clear START -> END we should
   #branch back to :Ret and look for another START
    t Ret
   #pattern space didnt start w/ END, but is there even
   #one at all? if so replace it w/ a newline followed
   #by an E so we'll recognize it at the next :Kil
    s|END|\
E|
   #if that last was successful we'll have a newline
   #but if not it means we need to get the next line
   #if the last line we've got unmatched pairs and are
   #currently in a delete cycle anyway, but maybe we
   #should print up to our START marker in that case?
    /\n/!{
       #i guess so. now that i'm thinking about it
       #we'll swap into hold space, and Print it
        ${  x;P;d
        }
       #get next input line and add S after the delimiting
       #newline because we're still in START state. Delete
       #will handle everything up to our marker before we
       #branch back to :Kil at the top of the script
        N
        s||&S|
    }
   #now Delete will slice everything from head of pattern space
   #to the first occurring newline and loop back to top of script.
   #because we've definitely made successful substitutions if we
   #have a newline at all we'll test true and branch to :Kil 
   #to go again until we've definitely got ^E
    D

...코멘트가 없습니다...

#!/usr/bin/sed -f
    t Kil
    :Ret
    /START/!b
    s||\
S|
    h;D
    :Kil
    /^E/{
        H;x
        s|\nS.*\nE||
    }
    t Ret
    s|END|\
E|
    /\n/!{
        ${  x;P;d
        }
        N
        s||&S|
    }
    D

주석이 달린 버전을 클립보드에 복사하고 다음을 수행합니다.

{ xsel; echo; } >se.sed
chmod +x se.sed
./se.sed <se.sed

#!/usr/bin/sed -f
####replace everything between
   #branch to :Kil if a successful substitution
   #has already occurred. this can only happen
   #if pattern space has been Deleted earlier
    t Kil
   #set a Ret :label so we can come back here
   #when we've cleared a  occurrence
   #and check for another if need be
    :Ret
   #if no  at the head of
   #pattern space.
    :Kil
   #do we?
    /^E/{
       #if so, we'll append it to our earlier save
       #and slice out everything between the two newlines
       #we've managed to insert at just the right points
        H;x
        s|\nS.*\nE||
    }
   #if we did just clear  we should
   #branch back to :Ret and look for another , but is there even
   #one at all? if so replace it w/ a newline followed
   #by an E so we'll recognize it at the next :Kil
    s|END|\
E|
   #if that last was successful we'll have a newline
   #but if not it means we need to get the next line
   #if the last line we've got unmatched pairs and are
   #currently in a delete cycle anyway, but maybe we
   #should print up to our

답변3

파일이 test.txt이면 다음을 사용할 수 있습니다.

sed ':a;N;$!ba;s/\n/ /g' test.txt|sed 's/\\{{\[}.*{\]}\\}//' 

첫 번째 sed는 모든 줄 바꿈을 제거하고 두 번째 sed는 태그 내의 텍스트를 제거합니다.

좀 더 일반적인 해결책이 필요한지 모르겠습니다.

관련 정보