[linux] sed의 ‘홀드 스페이스’와 ‘패턴 스페이스’의 개념

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 가지 명령은 정말 혼란 스럽습니다.



답변

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명령이 하는 일을 정확히 수행합니다. 파일을 반대로 인쇄합니다.


답변

@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가 더 적합 할 수 있습니다.


답변

@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 튜토리얼 은 매우 좋은 참고 자료입니다.


답변