sed의 '홀드 스페이스'와 '패턴 스페이스'의 개념


88

sed의 두 가지 개념 인 홀드 공간과 패턴 공간이 혼란 스럽습니다. 누군가 그들을 설명 할 수 있습니까?

다음은 매뉴얼의 일부입니다.

h H    Copy/append pattern space to hold space.
g G    Copy/append hold space to pattern space.

n N    Read/append the next line of input into the pattern space.

이 6 가지 명령은 정말 혼란 스럽습니다.


4
스스로를보십시오 :echo $'1\n2\n3\n4' | sed -n '1~2h;2~2{p;x;p}'
choroba

4
혼동하지 말고 사용하지 마십시오. 한 줄의 간단한 대체 이외의 경우에는 sed가 아닌 awk를 사용해야합니다. 보류 공간, 패턴 공간 및 sed 언어 구성의 95 %는 더 나은 대안이없는 awk 이전에 발명되었습니다. 1970 년대 중반에 awk가 발명 되 자마자 쓸모 없어졌고, awk에서 간단하고 은밀하게하기보다는 seds 신비한 구문을 사용하여 문제를 해결하는 것을 즐기는 사람들에 의해서만 살아 남았습니다. sed에서 s, g 및 p (-n 포함) 이상을 사용하는 경우 거의 확실하게 잘못된 도구를 사용하고있는 것입니다.
Ed Morton

27
Morton awk는 구조화 된 데이터로 작동합니다 (각 줄은 동일한 구조를 가짐). Sed는 원시 임의 데이터로 작업하기위한 것입니다. 따라서 단순히 sed 대신 awk를 사용할 수는 없습니다.
Pithikos 2014 년

5
읽기를 강력히 권장 info sed합니다. 맨 페이지보다 훨씬 더 자세합니다.
페르난도 바소

4
나는 Pithikos에 동의합니다. 나는 Morton이 한 것처럼 차선을 따라 내려가 Morton이 한 것과 같은 질문을 스스로에게 물었습니다. 그러나 나는 아직 쉽게 sed를 무시할 수 없었다.
eigenfield 2017 년

답변:


117

sed가 파일을 한 줄씩 읽을 때 현재 읽은 줄은 패턴 버퍼 (패턴 공간)에 삽입됩니다 . 패턴 버퍼는 현재 정보가 저장되는 스크래치 패드 인 임시 버퍼와 같습니다. sed에게 인쇄를 지시하면 패턴 버퍼를 인쇄합니다.

홀드 버퍼 / 홀드 공간은 sed가 다른 라인을 처리 할 때 무언가를 잡아서 저장하고 나중에 재사용 할 수있는 장기 저장 공간과 같습니다. 보류 공간을 직접 처리하지 않고 대신 복사하거나 패턴 공간에 추가해야합니다. 예를 들어, print 명령 p은 패턴 공간 만 인쇄합니다. 마찬가지로 s패턴 공간 에서 작동합니다.

다음은 그 예입니다.

sed -n '1!G;h;$p'

(-n 옵션은 행의 자동 인쇄를 억제합니다)

여기에는 세 가지 명령이 있습니다. 1!G, h$p. 1!G주소 1(첫 번째 줄)가 있지만 !명령이 첫 번째 줄을 제외한 모든 곳 에서 실행된다는 의미입니다 . $p반면에 마지막 줄에서만 실행됩니다. 그래서 일어나는 일은 다음과 같습니다.

  1. 첫 번째 줄을 읽고 패턴 공간에 자동으로 삽입
  2. 첫 번째 줄에서는 첫 번째 명령이 실행되지 않습니다. h첫 번째 줄을 보류 공간에 복사합니다 .
  3. 이제 두 번째 줄은 패턴 공간에 있던 모든 것을 대체합니다.
  4. 두 번째 줄에서 먼저를 실행 G하여 보류 버퍼의 내용을 패턴 버퍼에 추가하고 줄 바꿈으로 구분합니다. 이제 패턴 공간에는 두 번째 줄, 줄 바꿈 및 첫 번째 줄이 포함됩니다.
  5. 그런 다음 hcommand는 패턴 버퍼의 연결된 내용을 보류 공간에 삽입하여 이제 반전 된 행 2와 1을 보유합니다.
  6. 3 번 행으로 이동합니다. 위의 지점 (3)으로 이동합니다.

마지막으로 마지막 행을 읽고 보류 공간 (역순으로 이전의 모든 행을 포함)이 패턴 공간에 추가 된 후 패턴 공간이로 인쇄됩니다 p. 짐작했듯이 위는 tac명령이 하는 일을 정확히 수행합니다. 파일을 반대로 인쇄합니다.


3
G 및 h 옵션이 "잘라 내기 및 추가"처럼 작동합니까 ?? "복사 및 추가"작업처럼 보이지 않습니다.
Smile

중첩 된 명령 (중괄호)을 사용할 때 패턴을 추가하고 공백을 유지하는 것은 무엇입니까? '195,210{/add/p}'… 패턴에 관련된 라인 그룹의 마지막 라인을 추출 할 수 있습니까?
Sandburg

17

@Ed Morton : 여기에 동의하지 않습니다. 나는 sed매우 유용하고 간단하다는 것을 알았다 (패턴의 개념을 파악하고 버퍼를 유지하면).

예를 들어, 호스트 이름과 각 호스트에 대한 몇 가지 정보가있는 텍스트 파일을 가져 와서 그 사이에 내가 신경 쓰지 않는 쓰레기가 많이 들어갑니다.

Host: foo1
some junk, doesnt matter
some junk, doesnt matter
Info: about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Info: a second line about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Host: foo2
some junk, doesnt matter
Info: about foo2 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter

나에게 호스트 이름과 해당 info줄을 가져 오는 awk 스크립트 는 sed로 할 수있는 것보다 조금 더 걸릴 것입니다.

sed -n '/Host:/{h}; /Info/{x;p;x;p;}' myfile.txt

출력은 다음과 같습니다.

Host: foo1
Info: about foo1 that I really care about!!
Host: foo1
Info: a second line about foo1 that I really care about!!
Host: foo2
Info: about foo2 that I really care about!!

( Host: foo1출력에 두 번 나타납니다.)

설명:

  1. -n 명시 적으로 인쇄되지 않는 한 출력을 비활성화합니다.
  2. 첫 번째 일치, Host:행을 찾아서 보류 버퍼 (h)에 넣습니다.
  3. 두 번째 일치는 다음 Info : 행을 찾지 만 먼저 패턴 버퍼에서 현재 행을 홀드 버퍼와 Host:교환 (x)하고 행을 인쇄 (p) 한 다음 Info : 행을 다시 교환 (x)하고 인쇄 (p)합니다.

예, 이것은 단순한 예이지만 간단한 sed one-liner로 빠르게 처리 된 일반적인 문제라고 생각합니다. 주어진 예측 가능한 시퀀스에 의존 할 수없는 작업과 같이 훨씬 더 복잡한 작업의 경우 awk가 더 적합 할 수 있습니다.


2
이 경우에는 grep을 사용할 수 있습니다.grep 'Host\|Info'
Pithikos

주어진 호스트 뒤에 두 개의 Info 줄이 있으면 @JensJenson은 두 Info 줄 앞에 Info 줄이 오기를 원합니다. 그에 따라 답변을 편집 할 것 같습니다. Pithikos, grep은 충분하지 않습니다.
Aaron McDaid 2014

4
@JensJenson는 awk당신의 SED 코드의 상당 꽤 짧은 :awk '/Host:/{hold=$0}; /Info/{print hold; print;}' myfile.txt
아론 McDaid

13

@January의 답변과 예는 좋지만 설명이 충분하지 않았습니다. 정확히 어떻게 sed -n '1!G;h;$p'작동 하는지 이해할 수있을 때까지 많은 것을 검색하고 배워야했습니다 . 그래서 저 같은 사람을 위해 명령에 대해 자세히 설명하고 싶습니다.

먼저 명령이 수행하는 작업을 살펴 ​​보겠습니다.

$ echo {a..d} | tr ' ' '\n' # Prints from 'a' to 'd' in each line
a
b
c
d
$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;$p'
d
c
b
a

tac명령 처럼 입력을 반전합니다 .

sed한 줄씩 읽으므로 각 줄의 패턴 공간유지 공간 에서 어떤 일이 발생하는지 살펴 보겠습니다 . 마찬가지로 h명령 복사 보류 공간 패턴 영역의 내용을 모두 공간은 동일한 텍스트있다.

Read line    Pattern Space / Hold Space    Command executed
-----------------------------------------------------------
a            a$                            h
b            b\na$                         1!G;h
c            c\nb\na$                      1!G;h
d            d\nc\nb\na$                   1!G;h;$p

마지막 줄에는 다음과 같은 형식으로 $p인쇄 d\nc\nb\na$됩니다.

d
c
b
a

각 행의 패턴 공간을 보려면 l명령을 추가 할 수 있습니다 .

$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;l;$p'
a$
b\na$
c\nb\na$
d\nc\nb\na$
d
c
b
a

sed가 어떻게 작동하는지 이해하는 비디오 튜토리얼을 시청하는 것이 매우 도움이 되었습니다. 그 사람은 각 공간이 단계별로 어떻게 사용되는지 보여줍니다. 보류 간격은 4 번째 자습서에서 참조되지만 .NET에 익숙하지 않은 경우 모든 비디오를 시청하는 것이 좋습니다 sed.

또한 GNU sed 문서Bruce Barnett의 Sed 튜토리얼 은 매우 좋은 참고 자료입니다.


2
뭔가를 추가하지 않는 한 모든 실용적인 목적을위한 보관 공간이 비어 있다는 점을 언급하는 것도 도움이 될 것이라고 생각합니다.
Naveed
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.