나는 sed를 더 잘 이해하려고 노력하고 있지만 온라인 문서와 매뉴얼 페이지를 반복적으로 탐색했음에도 불구하고 한 가지 혼란스럽습니다.
내가 그렇게 한다면: ( 이내 bash
)
echo "
alpha
beta
gamma" | sed '1!G;h'
이해합니다:
alpha
beta
alpha
gamma
beta
alpha
1!G
따라서 라인 1을 제외한 각 입력 라인 뒤에 새 라인이 추가된다는 것을 알고 있습니다 . 그런 다음 h
패턴 공간을 예약된 공간에 복사합니다. 그러나 홀드 공간에서는 아무 일도 일어나지 않고 패턴 공간이 출력되어야 합니다. 이 시점에서 나는 다음 과 1!G;h
똑같은 출력을 볼 것으로 예상합니다 1!G
.
alpha
beta
gamma
보유 공간이 어떻게든 내보내지나요? 예약된 공간이 각 라인의 패턴 공간 다음에 출력된다면 sed 'h'
각 라인을 두 배로 늘리는 것은 어떨까요?
아, 저는 이것을 macOS Mojave 5에서 실행하고 있습니다 bash
. 어떤 버전을 사용하고 있는지는 모르겠지만 sed
최신 macOS와 함께 제공되는 기본 버전입니다.
답변1
G
첫 번째 명령은 썼지만 두 번째 명령은 작성한 예약된 공간에서 추가하는 것을 잊었습니다 .
sed h
각 주기에서 예약된 공간을 덮는 것이므로 각 행을 두 배로 늘리는 것이 아닙니다.
첫 번째 명령은 다음과 같습니다.
sed '1!G;h' <<END_INPUT
alpha
beta
gamma
END_INPUT
그리고 출력
alpha
beta
alpha
gamma
beta
alpha
첫 번째 줄을 제외한 모든 줄에 대해 구분 줄 바꿈을 사용하여 현재 예약된 공간을 패턴 공간에 추가합니다. 그런 다음 홀드 공간을 패턴 공간으로 덮어씁니다. 각 사이클이 끝나면(입력 라인을 처리한 후) 암시적 p
(인쇄) 명령이 있습니다.
이를 다르게 표현하면 "각 입력 줄에 대해 이전의 모든 줄을 역순으로 출력합니다(마지막으로 새 줄)"입니다.
그래서 코드는
alpha
패턴 공간으로 읽기 ,alpha
예약된 공간으로 복사, 인쇄alpha
,beta
패턴 공간으로 읽기 ,\nalpha
예약된 공간에서 패턴 공간으로 추가,beta\nalpha
예약된 공간에 복사, 인쇄beta\nalpha
,gamma
패턴 공간을 읽고 ,\nbeta\nalpha
예약된 공간에서 패턴 공간으로 추가하고,gamma\nbeta\nalpha
예약된 공간에 복사하고, 인쇄합니다gamma\nbeta\nalpha
.
암호
sed '1!G' <<END_INPUT
alpha
beta
gamma
END_INPUT
산출
alpha
beta
gamma
(세 번째 행과 마지막 행은 비어 있습니다.)
이 sed
코드는 입력의 각 줄을 출력하고 첫 번째 줄을 제외한 모든 줄에 추가 줄바꿈을 추가합니다. 그럴 것이기 때문에 이렇게 하는 것이다
alpha
패턴 공간을 읽고 , 인쇄하고alpha
,beta
패턴 공간을 읽고 ,\n
예약된 공간에서 패턴 공간으로 추가하고, 인쇄합니다beta\n
.gamma
패턴 공간을 읽고 ,\n
예약된 공간에서 패턴 공간에 추가하고, 인쇄합니다gamma\n
.
여기에 예약된 공간을 추가하면 G
패턴 공간의 끝에 추가 줄바꿈만 추가됩니다. 왜냐하면 패턴 공간은 항상 비어 있기 때문입니다(쓰기를 하지 않으므로).
답변2
내가 시도한 결과 :
]# echo -e "a\nb\nc\nd\ne\nf" |sed '1!G;h'
a
b
a
c
b
a
d
c
b
a
e
d
c
b
a
f
e
d
c
b
a
거꾸로 읽으면 "abcdef", "abcde", "abcd", "abc", "ab", "a"가 됩니다.
그걸 뭐라고 부르나요?
"G"가 추가되고 "h"가 대체되기 때문에 작동합니다. 이를 생략하면 G;h
블록 사이에 추가 빈 줄이 생깁니다.
info sed
"tac" 예가 있습니다:
sed -n '1!G;$p;h'
한 번만 인쇄하면( -n
및 $p
) 결과가 완전히 달라집니다. 마지막 "청크"입니다.sed '1!G;h'
Perl은 (이름이 지정된) 변수를 사용하여 이 알고리즘을 쉽게 에뮬레이트할 수 있습니다.
]# echo -e "a\nb\nc" | perl -ne '$hold = $_ . $hold; print $hold;'
a
b
a
c
b
a
들어오는 라인과 저장된 라인이 병합되는 방식을 반대로 바꿉니다.
]# echo -e "a\nb\nc" |perl -ne '$hold .= $_; print $hold;'
a
a
b
a
b
c
$_
입력라인입니다. H=H+선, H=선+H입니다. info sed
이 내용과 다른 미묘한 점을 발견하려면 주의 깊게 읽어야 합니다 .
답변3
더 간단한 것부터 시작해 보겠습니다.
$ seq 4 | sed 'G;h'
1
2
1
3
2
1
4
3
2
1
각 블록은 새로운 숫자를 추가하고 역순으로 인쇄합니다.
왜 이런 일이 발생합니까? 이 과정을 천천히 살펴보겠습니다.
1
sed는 seq (a)의 첫 번째 숫자(첫 번째 줄)를 받습니다. 선은 패턴 공간에 배치됩니다.- 실행될 첫 번째 명령은 이며
G
개행 문자를 추가하고 그 뒤에예비 공간현재 배치 공간으로 이동합니다. 먼저 (여기서와 같이) 예약된 공간은 비어 있으므로 sed는 개행 문자와 (공간 보존) 빈 문자열을 현재 패턴 공간에 추가합니다. 간단히 말해서, 입력의 첫 번째 줄에 개행 문자를 추가합니다. - 두 번째 명령은 입니다
h
. 패턴 공간을 예약된 공간으로 복사합니다. 이제 예약된 공간은1
개행 문자로 구성됩니다. - 명령 목록이 종료되었으므로 sed에는 옵션이 없기 때문에 sed는 패턴 공간(a
1
다음에 개행 문자)을 인쇄합니다-n
. 그런 다음 다음 입력 줄로 반복합니다. - 이제 sed는 두 번째 라인 a를 가져
2
와서 패턴 공간에 배치합니다. - 첫 번째 명령은 G입니다. 따라서 sed는 패턴 공간에 추가된 공간(
1
위에서 언급한 a 및 줄바꿈, 더 짧은 형식으로 작성됨 : )을 예약합니다.1\n
이제 패턴 공간이 설정되었습니다2\n1\n
. - 패턴 공간에 포함된 내용이 인쇄됩니다. sed는 다시 루프합니다.
- 세 번째
G
줄\n2\n1\n
에는3
. - 이 패턴 공간을
3\n2\n1\n
예약된 공간으로 복사하는 데 사용됩니다h
. - 또한 패턴 공간은 sed 스크립트 끝에 인쇄됩니다.
- 마지막 행까지 반복하고 반복합니다.
위의 모든 내용은 라인을 역순으로 캡처하는 것과 동일합니다.
이 스크립트를 사용하면 상황이 더 명확해질 수 있습니다(인용 패턴 공백 사용 l
).
$ seq 5 | sed -n 'G;h;l'
1\n$
2\n1\n$
3\n2\n1\n$
4\n3\n2\n1\n$
5\n4\n3\n2\n1\n$
그리고 원본 스크립트에서는 첫 번째 줄에 개행 문자를 추가하지 않습니다.
$ seq 5 | sed -n '1!G;h;l'
1$
2\n1$
3\n2\n1$
4\n3\n2\n1$
5\n4\n3\n2\n1$
이제 알파, 베타 및 감마를 사용하십시오.
$ printf 'alpha\nbeta\ngamma' | sed -n '1!G;h;l'
alpha$
beta\nalpha$
gamma\nbeta\nalpha$
원래 sed 스크립트로 돌아가 보겠습니다.
$ printf 'alpha\nbeta\ngamma' | sed '1!G;h'
alpha
beta
alpha
gamma
beta
alpha
실제로 IMO는 다음과 같아야 합니다.
$ printf 'alpha\nbeta\ngamma' | sed '1!G;h;$!d'
gamma
beta
alpha
모든 줄이 역순으로 되어 마지막 반복만 인쇄됩니다.