현재 실행 중인 sed에 추가하면 왜 작동하지 않나요?

현재 실행 중인 sed에 추가하면 왜 작동하지 않나요?

다음과 같은 텍스트 파일이 있습니다.

(empty) 
str
int
int 

s/^/\</g이것을 현재 sed에 추가하면 (make it 's/\&/\</g;s/\</\ /g;s/^/\</g') 이것이 출력됩니다.

< ##only this line gets a < 
str
int
int 

그러나 예를 들어 새 줄을 만들고 전체 명령을 입력하면 sed -i '' 's/^/\</g' *.p*다음과 같은 결과가 출력됩니다.

< 
<str
<int
<int 

차이점이 뭐야?

답변1

차이점은 입력과 출력입니다. 첫 번째 경우에는 \n개행을 삽입했습니다. 하지만 여전히 동일한 패턴 공간에서 작업하고 있으므로 ^패턴 공간의 헤드는 삽입된 개행이 포함되어 있더라도 제자리에 남아 있습니다. 이것이 발생할 때마다 개행을 삽입하게 됩니다 <.

그러나 두 번째 경우에는 new를 사용 sed하고 마지막 seds 출력을 입력으로 읽습니다. 따라서 모든 개행은 이제 별도의 입력 행으로 첫 번째 루프 카운트와 함께 주입되고 각 개행에는 자체 ^패턴 공간 헤더가 있습니다.

echo ..... | 
sed 's/./&\
/g;s/^/sed1/' |
sed 's/^/sed2/'

sed2sed1.
sed2.
sed2.
sed2.
sed2.
sed2

그런데...

sed 's/&/</g;s/</\
/g'

...쓰기가 더 쉬울 수도 있습니다...

sed 'y/&</\n\n/'

...하지만 각각 뒤에 줄 바꿈을 추가 [&<]하고 각각을 바꾸려면 &다음 <을 수행할 수 있습니다.

sed 's/[&<]/<\
/g'

...하지만 출력이 입력과 전혀 일치하지 않습니다...

답변2

sed 'expression;expression' 

동일합니까?

sed -e 'expression' -e 'expression'

그 중 여러 곳에서단순한케이스와 함께

sed -e 'expression' | sed -e 'expression'

귀하의 경우 (내가 아는 한) 모든 것을 &로 변경 <한 다음 <모두 래핑하고 마지막으로 <줄 시작 부분에 추가하려고 합니다.

s/\&/\</g;s/\</\
/g;s/^/\</g

주어진 입력을 기반으로 이 sed스크립트는 BSD를 사용하여 다음을 수행합니다 sed.

$ sed -f script.sed file
<
<

<

<

또는 GNU를 사용하십시오 sed.

$ gsed -f script.sed file
<
<
str
<
int
<
int

왜 이런거야?

  1. 첫째, &파일에 아무 것도 없으므로( \이전 것들은 &추가로 제거할 수 있음) 첫 번째 표현식은 아무 작업도 하지 않습니다.
  2. 두 번째 표현은 \<단어 경계(시작)와 일치합니다. 솔직히 말해서 BSD가 왜 이 텍스트를 제거했는지 조금 혼란스럽습니다 sed(이것이 OpenBSD의 버그인지 살펴보겠습니다 sed). 따라서 예제 파일의 각 단어 시작 부분에 개행 문자가 삽입됩니다.
  3. 세 번째 표현식은 여전히 ​​동일한(현재 수정된) 입력 라인에서 작동하며 <라인 시작 부분에 a를 삽입합니다.

대조적으로, 단일 표현식 s/^/\</g( \이전 <g수정자가 필요하지 않은 경우)은 단순히 <각 행의 시작 부분에 a를 삽입합니다.


후속 조치: sedOpenBSD 6.1-stable 구현 시 삽입된 개행 문자로 시작하는 줄에 문자열을 추가하는 것과 관련된 버그가 확인되었습니다. 패치가 제출되었습니다.

관련 정보