그래서 나는 다음 질문에 답하고 싶다.sed + 존재하지 않는 경우에만 문자열 앞에 단어를 추가합니다.그리고sed - 앞의 문자가 특정 문자가 아닌 경우 문자열의 문자를 대체합니다.그리고 한 단계 더 나아가세요.
_
로 완전히 바꾸고 싶은 파일이 있지만 \_
두 가지 제한 사항이 있다고 가정해 보겠습니다.
_
이미 이전이 있다면 아무\
일도 일어나지 않기를 바랍니다. (저희는 한 번도 받아본 적이 없으니\\
걱정하지 마세요)- 우리는해야한다오직
_
두 개의 구분 기호 앞에 나타나는 경우 다음과 같이 대체하십시오. 예를 들어start[
와 사이입니다]end
.
예를 들어 다음과 같습니다.
Pretending_we have \_ some start[text that\_is really_cool]end.
Then \_nothing_ would start[happen_ to\_ that crew_]end
로 변환됩니다
Pretending_we have \_ some start[text that\_is really\_cool]end.
Then \_nothing_ would start[happen\_ to\_ that crew\_]end
노트:\_
어떤 경우에는 각 인스턴스를 사용되지 않은 인스턴스로 교체한 다음 _
모든 인스턴스를 해당 인스턴스로 교체 \_
하고 첫 번째 변경 사항을 되돌리는 방식 으로 sed를 연결하기를 원한다는 것을 알고 있습니다 . 하지만 코드에 다른 어떤 문자가 있을지 모르기 때문에 그렇게 하고 싶지는 않고, 가능하다면 직접 해보고 싶습니다.
또한 vim과 터미널에서 이 작업을 수행할 예정입니다(vim이 작동하는지 확인하기 위해 테스트로 실행한 다음 터미널에서 11개의 다른 파일에 대해 작업합니다.) 차이점을 잘 이해하지는 못하지만, 하나가 다른 것보다 쉬울 경우에 대비해 언급하겠습니다.
편집하다:제기된 몇 가지 질문에 답하려면:
- perl/sed/vim은 모두 이 문제를 처리하는 데 허용되는 방법입니다. 최선의 접근 방식이 무엇인지 잘 모르겠습니다. 저는 sed/vim의 정규식에 더 익숙하므로 이에 대해 언급했습니다. (sed와 vim을 혼동하여 혼란을 야기한 것 같습니다. 그 점에 대해 매우 유감스럽게 생각합니다. 저는 대부분의 정규식 요구사항에 sed와 vim 정규식을 사용하는 데 익숙하며, 제가 알아낸 바에 따르면 일반적으로 나는 그것이 sed와 vim에서 완벽하게 작동하므로 그들이 동일한 정규식 처리를 사용한다고 가정하지만 그것은 아마도 내가 만들어야 할 안전한 가정이 아닐 것이며 이에 대해 조사할 것입니다.
- 우분투를 사용하고 있어요
- 일반적으로 시작/끝 구분 기호는 같은 줄에 있으므로 이론적으로 이는 안전한 가정이 될 수 있습니다(비록 방법을 안다면 줄은 중요하지 않지만 미래의 사람들에게는 살펴보는 것도 유익합니다 그런 문제에)
답변1
나는 perl
그것을 사용할 것입니다 :
perl -pe 's{start\[.*?\]end}{$& =~ s{\\?_}{\\_}gr}ge' < your-file
s
모든 ( g
) start[...]end
시퀀스를 동일한 시퀀스( $&
정규 표현식이 일치하는 내용을 포함)로 바꾸고 선택적으로 ( ) 앞에 오는 모든 ( ) 을 s
바꾸고 반환합니다 . 이 플래그는 replacement( )가 코드로 평가됨을 나타냅니다.r
g
_
?
\
\_
e
$& =~ s{\\?_}{\\_}gr
e
중첩이 없다고 가정합니다 start[...]end
.
start[...]end
s가 여러 줄에 걸쳐 있을 수 있는 경우 -0777
입력이 한 번에 한 줄이 아닌 전체적으로 처리되도록 이 옵션(레코드 구분 기호를 불가능한 값으로 설정)을 추가합니다.
s/pattern/replacement/flags
¹ in 과 동일한 방법을 사용합니다 sed
. 단, in 에서는 perl
작성할 수도 있습니다 s{pattern}{replacement}flags
. 이는 중첩 및 가독성에 도움이 됩니다.
답변2
GNU sed 전용:
sed -r ':1;s/(start\[.*[^\])(_.*\]end)/\1\\\2/;t1' file
대체를 수행해야 하는 경우 -i
이 플래그를 마지막에 설정하십시오.-ri
답변3
이를 수행하려면 awk 명령을 사용할 수 있습니다. 대괄호는 #과 같은 다른 문자로 임시로 편리하게 바꿀 수 있습니다.
cat yourfile.txt| tr '[]' '#'
이제 위의 결과를 다음 명령으로 파이프합니다.
awk -F# 'OFS=""; {for (i=1;i<=NF; i++) if(i%2==0){ gsub("\\\\","",$i);gsub("_","\\_",$i);$i="["$i"]"} print $0}'
답변4
다중 문자 및 세 번째 인수에 GNU RS
awk RT
사용 match()
:
$ awk -v RS=']end' '{ORS=RT} match($0,/(.*start\[)(.*)/,a) { gsub(/\\?_/,"\\_",a[2]); $0=a[1] a[2] } 1' file
Pretending_we have \_ some start[text that\_is really\_cool]end.
Then \_nothing_ would start[happen\_ to\_ that crew\_]end