N을 사용할 때 sed 출력에 대해 혼동됩니다. 누군가 이 결과를 설명할 수 있나요?

N을 사용할 때 sed 출력에 대해 혼동됩니다. 누군가 이 결과를 설명할 수 있나요?

나는 sed를 배우고 있습니다. N(다음에 여러 줄)을 누르기 전까지는 모든 것이 잘 진행되는 것 같습니다. 연습/이해/컨텍스트 목적으로 이 파일(guide.txt)을 만들었습니다. 파일 내용은 이렇습니다...

This guide is meant to walk you through a day as a Network
Administrator. By the end, hopefully you will be better
equipped to perform your duties as a Network Administrator
and maybe even enjoy being a Network Administrator that much more.
Network Administrator
Network Administrator
I'm a Network Administrator

따라서 내 목표는 "네트워크 관리자"의 모든 인스턴스를 "시스템 사용자"로 바꾸는 것입니다. "Network Admin"의 첫 번째 인스턴스는 줄 바꿈(\n)으로 구분되므로 "Admin"으로 시작하고 "Network\n"으로 끝나는 줄을 이전 행에 추가하려면 여러 줄의 다음 연산자(N)가 필요합니다. 괜찮아요. 하지만 다른 모든 "Network Manager" 단일 인스턴스도 캡처하고 싶습니다.

내 연구에 따르면 개행으로 구분된 문자열에 대해 하나, 다른 문자열에 대해 하나라는 두 개의 대체 명령이 필요하다는 것을 알고 있습니다. 또한 마지막 줄에 대체 일치 항목과 다음 여러 줄이 포함되어 있으므로 일부 자이브가 발생합니다. 그래서 이걸 만들었어요...

$ sed '
> s/Network Administrator/System User/
> N
> s/Network\nAdministrator/System\nUser/
> ' guide.txt

그러면 다음 결과가 반환됩니다...

This guide is meant to walk you through a day as a System
User. By the end, hopefully you will be better
equipped to perform your duties as a System User
and maybe even enjoy being a Network Administrator that much more.
System User
Network Administrator
I'm a System User

나는 한 줄 바꾸기가 "네트워크 관리자"의 모든 "일반" 인스턴스를 캡처하여 "시스템 사용자"로 바꿀 것이라고 생각했으며 여러 줄 문은 개행으로 구분된 인스턴스에서 마법을 작동할 것이라고 생각했지만 보시다시피 반환됨을 고려했습니다. 예상치 못한 결과.

좀 헤매다가 이걸 발견했습니다...

$ sed '
> s/Network Administrator/System User/
> N
> s/Network\nAdministrator/System\nUser/
> s/Network Administrator/System User/
> ' guide.txt

자, 보라, 나는 원하는 결과를 얻었습니다 ...

This guide is meant to walk you through a day as a System
User. By the end, hopefully you will be better
equipped to perform your duties as a System User
and maybe even enjoy being a System User that much more.
System User
System User
I'm a System User

왜 이것이 작동하지만 원래 sed 스크립트는 작동하지 않습니까? 나는 이것을 정말로 이해하고 싶습니다.

도움을 주셔서 미리 감사드립니다.

답변1

먼저 귀하의 솔루션이 실제로 작동하지 않는다는 점에 유의하십시오. 다음 테스트 파일을 고려해보세요.

$ cat test1
Network
Administrator Network
Administrator

그런 다음 다음 명령을 실행합니다.

$ sed '
 s/Network Administrator/System User/
 N
 s/Network\nAdministrator/System\nUser/
 s/Network Administrator/System User/
 ' test1
System
User Network
Administrator

문제는 코드가 마지막 코드를 대체하지 않는다는 것입니다 Network\nAdministrator.

이 솔루션은 작동합니다.

$ sed ':a; /Network$/{$!{N;ba}}; s/Network\nAdministrator/System\nUser/g; s/Network Administrator/System User/g' test1
System
User System
User

우리는 이것을 다음에도 적용할 수 있습니다 guide.txt:

$ sed ':a; /Network$/{$!{N;ba}}; s/Network\nAdministrator/System\nUser/g; s/Network Administrator/System User/g' guide.txt 
This guide is meant to walk you through a day as a System
User. By the end, hopefully you will be better
equipped to perform your duties as a System User
and maybe even enjoy being a System User that much more.
System User
System User
I'm a System User

핵심은 요구 사항에 맞는 것을 찾을 때까지 한 줄씩 계속 읽는 것입니다.아니요완료 Network되면 교체할 수 있습니다.

호환성 참고 사항:위의 내용은 모두 \n대체 텍스트에 사용됩니다. 이를 위해서는 GNU sed가 필요합니다. BSD/OSX sed에서는 작동하지 않습니다.

[쪽으로필립스.]

여러 줄 버전

이해하는 데 도움이 된다면 동일한 명령을 여러 줄로 나누어서 설명하겠습니다.

$ sed ':a
    /Network$/{
       $!{
           N
           ba
       }
    }
    s/Network\nAdministrator/System\nUser/g
    s/Network Administrator/System User/g
    ' filename

어떻게 작동하나요?

  1. :a

    그러면 라벨이 생성됩니다 a.

  2. /Network$/{ $!{N;ba} }

    줄이 로 끝나면 Network다음과 같습니다.아니요마지막 줄( $!)은 다음 줄( N)을 읽고 추가하고 레이블 a( ba)로 다시 분기됩니다.

  3. s/Network\nAdministrator/System\nUser/g

    중간 개행 문자로 바꾸세요.

  4. s/Network Administrator/System User/g

    중간 공백으로 교체합니다.

더 간단한 솔루션(GNU에만 해당)

GNU sed 사용(아니요BSD/OSX), 대체 명령만 필요합니다:

$ sed -zE 's/Network([[:space:]]+)Administrator/System\1User/g' test1
System
User System
User

그리고 guide.txt파일에:

$ sed -zE 's/Network([[:space:]]+)Administrator/System\1User/g' guide.txt 
This guide is meant to walk you through a day as a System
User. By the end, hopefully you will be better
equipped to perform your duties as a System User
and maybe even enjoy being a System User that much more.
System User
System User
I'm a System User

이 예에서는 -zsed에게 첫 번째 NUL 문자를 읽도록 지시합니다. 텍스트 파일에는 null 문자가 포함될 수 없으므로 전체 파일을 한 번에 읽는 효과가 있습니다. 그러면 행을 잃을 염려 없이 대체를 수행할 수 있습니다.

파일이 큰 경우(일반적으로 기가바이트를 의미함) 이 방법은 적합하지 않습니다. 너무 큰 경우 한 번에 모두 읽으면 시스템 RAM에 부담을 줄 수 있습니다.

GNU 및 BSD sed용 솔루션

제안대로필리포스, 휴대용 솔루션은 다음과 같습니다.

sed 'H;1h;$!d;x;s/Network\([[:space:]]\)Administrator/System\1Us‌​er/g'

답변2

그 동안 sed시간을 ​​내어 @John1024의 답변에 추가하겠습니다.

\n1) 대체 문자열에 무엇을 사용하고 있는지 확인하십시오. 이것은 GNU에서 작동 sed하지만 POSIX의 일부가 아니므로 n다른 많은 s sed에 백슬래시와 an을 삽입 합니다( \n그런데 패턴에서 사용할 때 이식 가능합니다).

대신에 다음을 권장합니다 s/Network\([[:space:]]\)Administrator/System\1Us‌​er/g. [[:space:]]개행이나 공백과 일치하므로 두 개의 s명령이 필요하지 않고 하나로 병합합니다. 다음으로 둘러싸 \(...\)대체 항목에서 참조할 수 있습니다 . \1첫 번째 쌍에서 일치하는 항목으로 대체됩니다 \(\).

2) 두 줄의 패턴을 올바르게 일치시키려면 패턴을 알아야 합니다 N;P;D.

 sed '$!N;s/Network\([[:space:]]\)Administrator/System\1User/g;P;D'

항상 N다음 줄을 추가합니다(마지막 줄을 제외하고 이것이 "주소가 지정된" 이유입니다 $!(= 마지막 줄이 아닌 경우; 실수로 스크립트를 종료하지 않도록 항상 계속 고려해야 합니다). 그런 다음 교체 후에는 N첫 번째 줄만 인쇄합니다. 패턴 공간 한 줄에서 해당 줄을 제거하고 원래 의도였던 나머지 패턴 공간(다음 줄을 읽지 않고)을 사용하여 다음 루프를 시작합니다.$!PD

이 패턴을 기억하세요. 자주 필요할 것입니다.

3) 여러 줄 편집을 위한 또 다른 유용한 패턴, 특히 두 줄 이상이 관련된 경우: John에게 제안한 것처럼 공간을 모아 두십시오.

sed 'H;1h;$!d;g;s/Network\([[:space:]]\)Administrator/System\1Us‌​er/g'

설명을 위해 반복하겠습니다. H각 행을 예약된 공간에 추가합니다. 이로 인해 첫 번째 줄 앞에 추가 개행이 발생하므로 첫 번째 줄을 추가하는 대신 이동해야 합니다 1h. 다음은 $!d"마지막 줄을 제외한 모든 줄에 대해 패턴 공간을 제거하고 다시 시작"을 의미합니다. 따라서 나머지 스크립트는 마지막 줄에 대해서만 실행됩니다. 이때 전체 파일은 예약된 공간에 모아져(매우 큰 파일에는 사용하지 마세요!) 패턴 공간으로 이동되므로 GNU 옵션을 사용하는 것처럼 g한번에 모든 교체를 수행 할 수 있습니다 .-zsed

이는 제가 기억해두기를 권장하는 또 다른 유용한 패턴입니다.

관련 정보