이 질문에 대한 의견 에서 다양한 sed 구현이 상당히 간단한 프로그램에 동의하지 않은 경우가 생겼으며 우리 (또는 적어도 I)는 사양이 실제로 필요한 것을 결정할 수 없었습니다.
문제는 삭제 된 줄에서 시작하는 범위의 동작입니다.
1d;1,2d
해당 명령에 도달하기 전에 범위의 시작을 제거하더라도 2 행을 삭제해야합니까 ? 나의 초기 기대는 BSD sed와 "no"였고, GNU sed는 "yes"라고 말하고 사양 텍스트를 검사해도 문제가 완전히 해결되지는 않습니다.
내 기대와 일치하는 것은 (적어도) macOS와 Solaris sed
및 BSD sed
입니다. 의견이 맞지 않다는 것은 GNU와 Busybox (최소한)이며 sed
여기에 많은 사람들이 있습니다. 처음 두 개는 SUS 인증을 받았으며 다른 두 개는 더 널리 퍼져있을 것입니다. 어떤 행동이 올바른가요?
두 주소 범위 의 사양 텍스트 는 다음과 같습니다.
나오지 명령이 다음주기 또는 종료 될 시작할 때까지 유틸리티는 다음 순서 누구의 주소가 패턴 공간을 선택 모든 명령에 적용된다.
과
두 개의 주소를 가진 편집 명령은 첫 번째 주소와 일치하는 첫 번째 패턴 공간에서 두 번째 주소와 일치하는 다음 패턴 공간을 포함하는 범위를 선택해야합니다. [...] 선택한 범위 다음의 첫 번째 줄부터 sed는 첫 번째 주소를 다시 찾습니다. 그 후, 과정이 반복되어야한다.
2 행 은 시작점이 삭제되었는지 여부에 관계없이 "첫 번째 주소와 일치하는 첫 번째 패턴 공간에서 두 번째와 일치하는 다음 패턴 공간을 포함하는 범위" 내에 있습니다. 반면에, 나는 첫 번째 d
사이클이 다음 사이클로 넘어갈 것으로 예상 하고 범위를 시작할 기회를주지 않았습니다. UNIX ™ 인증 구현은 예상 한대로 수행하지만 사양에서 요구하는 것은 아닙니다.
몇 가지 예시적인 실험이 뒤 따르지만 핵심 질문은 삭제 된 라인에서 범위가 시작될 때 어떻게 해야 sed
합니까?
실험 및 예
이 문제에 대한 간단한 데모는 다음과 같이 행을 삭제하지 않고 추가 사본을 인쇄합니다.
printf 'a\nb\n' | sed -e '1d;1,2p'
이것은 제공 sed
입력의 두 라인, a
및 b
. 이 프로그램은 다음 두 가지를 수행합니다.
로 첫 번째 줄을 삭제합니다
1d
.d
명령 것패턴 공간을 삭제하고 다음 사이클을 시작하십시오. 과
- 모든 라인이 수신하는 자동 인쇄 외에도 1에서 2까지의 라인 범위를 선택하고 명시 적으로 인쇄합니다. 따라서 범위에 포함 된 선이 두 번 나타납니다.
내 기대는 이것이 인쇄되어야한다는 것입니다.
b
1,2
라인 1 동안 도달하지 않았기 때문에 범위가 적용되지 않는 경우에만 ( d
이미 다음 사이클 / 라인으로 이동 했기 때문에 ) 범위 포함이 시작되지 않고 a
삭제 된 동안에는 범위 포함이 시작되지 않습니다 . sed
macOS 및 Solaris 10 의 호환되는 Unix sed
는 Solaris 및 BSD 의 비 POSIX와 마찬가지로이 출력을 생성합니다 sed
.
반면에 GNU sed는 다음을 인쇄합니다.
b
b
범위 를 해석 했음을 나타냅니다 . 이것은 POSIX 모드에서 발생합니다. Busybox의 sed는 동일한 동작을 갖지만 항상 동일한 동작은 아니므로 공유 코드의 결과가 아닌 것 같습니다.
추가 실험
printf 'a\nb\nc\nd\ne\n' | sed -e '2d;2,/c/p'
printf 'a\nb\nc\nd\ne\n' | sed -e '2d;2,/d/p'
삭제 된 줄에서 시작하는 범위가 다음 줄 에서 시작하는 것처럼 처리하는 것처럼 보입니다 . /c/
범위를 끝내기 위해 일치하지 않기 때문에 볼 수 있습니다 . 사용 /b/
범위를 시작하려면 않습니다 하지 와 동일하게 동작합니다 2
.
내가 사용했던 초기 작업 예는
printf '%s\n' a b c d e | sed -e '1{/a/d;};1,//d'
/a/
첫 번째 줄에있는 경우에도 (첫 번째 줄에있는 경우에도 GNU sed가 사용 0,/a/d
하는 것 – POSIX 호환 변환 시도) 모든 줄을 첫 번째 일치 항목 까지 삭제하는 방법 입니다.
첫 번째 줄이 일치하는 경우 (또는 두 번째로 일치하지 않는 경우 전체 파일) 두 번째 일치 항목을 삭제해야한다고 제안 /a/
되었지만, 다시 말하지만 GNU sed만이 그렇게합니다. macOS sed 및 Solaris sed 농산물
b
c
d
e
내가 예상했듯이 (GNU sed는 종료되지 않은 범위를 제거하여 빈 출력을 생성합니다. Busybox sed는 d
and 만 인쇄합니다 e
. 일반적으로 인증 적합성 테스트를 통과했다는 것은 자신의 행동이 정확하지만 많은 사람들이 확실하지 않다고 제안했지만 사양 텍스트가 완전히 설득력이 없으며 테스트 스위트를 신뢰할 수 없다고 가정합니다. 완벽하게 포괄적입니다.
오늘날 불일치로 인해 해당 코드를 작성하는 것은 실제로 휴대하기 쉽지 않지만 이론적 으로는 어느 의미 또는 다른 의미로 모든 곳에서 동일해야합니다. 나는 이것이 버그라고 생각하지만 어떤 구현에 대해보고 해야할지 모르겠습니다. 내 견해로는 현재 GNU와 Busybox sed의 동작이 사양과 일치하지 않지만 잘못 생각할 수 있습니다.
POSIX에 필요한 것은 무엇입니까?
ed
않고sed
완전히 무시 합니까?