sed는 특정 구분 기호 사이의 다른 문자 앞에 문자를 추가합니다.

sed는 특정 구분 기호 사이의 다른 문자 앞에 문자를 추가합니다.

그래서 나는 다음 질문에 답하고 싶다.sed + 존재하지 않는 경우에만 문자열 앞에 단어를 추가합니다.그리고sed - 앞의 문자가 특정 문자가 아닌 경우 문자열의 문자를 대체합니다.그리고 한 단계 더 나아가세요.

_로 완전히 바꾸고 싶은 파일이 있지만 \_두 가지 제한 사항이 있다고 가정해 보겠습니다.

  1. _이미 이전이 있다면 아무 \일도 일어나지 않기를 바랍니다. (저희는 한 번도 받아본 적이 없으니 \\걱정하지 마세요)
  2. 우리는해야한다오직_두 개의 구분 기호 앞에 나타나는 경우 다음과 같이 대체하십시오. 예를 들어 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개의 다른 파일에 대해 작업합니다.) 차이점을 잘 이해하지는 못하지만, 하나가 다른 것보다 쉬울 경우에 대비해 언급하겠습니다.

편집하다:제기된 몇 가지 질문에 답하려면:

  1. perl/sed/vim은 모두 이 문제를 처리하는 데 허용되는 방법입니다. 최선의 접근 방식이 무엇인지 잘 모르겠습니다. 저는 sed/vim의 정규식에 더 익숙하므로 이에 대해 언급했습니다. (sed와 vim을 혼동하여 혼란을 야기한 것 같습니다. 그 점에 대해 매우 유감스럽게 생각합니다. 저는 대부분의 정규식 요구사항에 sed와 vim 정규식을 사용하는 데 익숙하며, 제가 알아낸 바에 따르면 일반적으로 나는 그것이 sed와 vim에서 완벽하게 작동하므로 그들이 동일한 정규식 처리를 사용한다고 가정하지만 그것은 아마도 내가 만들어야 할 안전한 가정이 아닐 것이며 이에 대해 조사할 것입니다.
  2. 우분투를 사용하고 있어요
  3. 일반적으로 시작/끝 구분 기호는 같은 줄에 있으므로 이론적으로 이는 안전한 가정이 될 수 있습니다(비록 방법을 안다면 줄은 중요하지 않지만 미래의 사람들에게는 살펴보는 것도 유익합니다 그런 문제에)

답변1

나는 perl그것을 사용할 것입니다 :

perl -pe 's{start\[.*?\]end}{$& =~ s{\\?_}{\\_}gr}ge' < your-file

s모든 ( g) start[...]end시퀀스를 동일한 시퀀스( $&정규 표현식이 일치하는 내용을 포함)로 바꾸고 선택적으로 ( ) 앞에 오는 모든 ( ) 을 s바꾸고 반환합니다 . 이 플래그는 replacement( )가 코드로 평가됨을 나타냅니다.rg_?\\_e$& =~ s{\\?_}{\\_}gre

중첩이 없다고 가정합니다 start[...]end.

start[...]ends가 여러 줄에 걸쳐 있을 수 있는 경우 -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 RSawk 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

관련 정보