텍스트 파일에 다음과 같은 문자열 사이에 있는 모든 내용을 원하는 텍스트가 있습니다 \{{[}
.{]}\}
하고 싶습니다. 이 두 개의 문자열~할 수 있다같은 줄에 있을 뿐만 아니라 다른 줄에도 누워 있습니다. 두 경우 모두, ~에시작 부분이 있는 줄에서 \{{[}
앞의 텍스트, 즉 왼쪽의 텍스트가 삭제되는 것을 원하지 않습니다. 이후의 텍스트도 마찬가지입니다 {]}\}
.
예는 다음과 같습니다. 콘텐츠가 포함된 텍스트 파일이 제공됩니다.
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\E
something
정규식이 아닌 리터럴 문자열로 처리됩니다 .
일반 파일을 내부에서 수정하려면 다음 -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
. 따라서 수많은 백슬래시가 발생합니다.
그런 다음 우리가 해야 할 일은 다른 모든 레코드를 인쇄하는 것뿐입니다. 모든 홀수 레코드에 대해 (true) NR%2
입니다 .1
두 솔루션 모두 마커가 일치하고 해당 섹션이 중첩되지 않은 것으로 가정합니다.
최신 버전의 GNU를 사용하여 파일을 내부에서 수정하려면 ¹ 옵션을 awk
추가하세요 -i /usr/share/awk/inplace.awk
.
¹사용하지 마세요-i inplace
as 는 누군가 악성 코드를 심었을 수 있는 현재 작업 디렉터리에서 확장명(as 또는 )을 먼저 gawk
로드하려고 시도합니다 . 와 함께 제공되는 확장 프로그램 의 경로는 시스템에 따라 다를 수 있습니다.inplace
inplace
inplace.awk
inplace
gawk
gawk '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는 태그 내부의 텍스트를 제거합니다.
좀 더 일반적인 해결책이 필요한지 모르겠습니다.