전체 파일을 패턴 공간으로 읽는 것이 잘못 될 수있는 모든 이유가 있습니다. 마지막 줄을 둘러싼 질문의 논리 문제는 일반적인 문제입니다. sed
더 이상 라인이없고 sed
EOF가 발생 하면 라인 사이클 과 관련 이 있습니다 . 처리가 종료됩니다. 마지막 줄에 있고 sed
다른 줄 을 가져 오라고 지시 하면 바로 멈추고 더 이상 할 일이 없습니다.
즉, 전체 파일을 패턴 공간으로 읽어야하는 경우 다른 도구를 고려해 볼 가치가 있습니다. 사실, 스트림 편집기 sed
는 시연 적으로 한 번에 라인 또는 논리 데이터 블록을 작동하도록 설계되었습니다.
전체 파일 블록을보다 잘 처리 할 수있는 유사한 도구가 많이 있습니다. ed
그리고 ex
, 예를 들어, 많은 무엇을 할 수 sed
할 수있는 유사한 구문을 - 그리고 많은 다른 외에 -로하지만이 아닌 출력으로 변환하는 동안 입력 스트림에서만 동작하는 sed
않는, 그들은 또한 파일 시스템의 임시 백업 파일을 유지 . 그들의 작업은 필요에 따라 디스크에 버퍼링되며 파일 끝에서 갑자기 종료되지 않습니다 (그리고 버퍼 스트레인 하에서 훨씬 덜 자주 영향을 미치는 경향이 있습니다) . 더욱이 이들은 sed
스트림 컨텍스트에서 의미가없는 여러 가지 유용한 기능을 제공합니다. 이는 라인 마크, 실행 취소, 명명 된 버퍼, 조인 등과 같은 것입니다.
sed
이 회사의 주요 강점은 데이터를 읽는 즉시 빠르고 효율적으로 스트림 처리 할 수 있다는 것입니다. 당신이 파일을 후루룩 소리 내며 먹기 때 당신은 멀리 그것을 던져 그리고 당신은 당신이 언급 마지막 줄 문제 같은 상반된 어려움으로 실행하고 버퍼 오버런 경향이 있고, 한심한 성능 - 길이에 정규 표현식 엔진의 처리 시간 증가는 구문 분석 데이터와 일치하는 항목을 열거 할 때 기하 급수적으로 증가 합니다 .
그 마지막 시점에 관해서는 : 나는 예제 s/a/A/g
사례가 매우 순진한 예일 가능성이 높으며 입력을 위해 수집하려는 실제 스크립트가 아닐 수도 있음을 이해하지만 익숙해 지려면 가치가 있음을 알 수 있습니다 y///
. g
하나의 문자를 다른 문자로 대체하는 경우가 많을 y
경우 매우 유용 할 수 있습니다. 대체와 반대로 변환이며 정규 표현식을 암시하지 않기 때문에 훨씬 빠릅니다. 후자의 요점은 빈 //
주소는 영향을 미치지 않지만 영향을받을 수 있으므로 빈 주소 를 유지하고 반복하려고 할 때 유용 할 수 있습니다. 어쨌든 y/a/A/
동일한 것을 달성하는보다 간단한 방법이며 다음과 같이 스왑이 가능합니다.y/aA/Aa/
이것은 모든 대문자 / 소문자를 서로 줄로 바꾸는 것입니다.
또한 당신이 묘사하는 행동이 실제로 일어날 일이 아니라는 점에 유의해야합니다.
GNU이다에서 info sed
에서 일반적으로보고 된 버그의 섹션 :
N
마지막 줄에 명령
명령이 파일의 마지막 행에 발행 sed
될 때 아무것도 인쇄하지 않고 대부분의 종료 버전 N
. sed
물론 -n
명령 스위치가 지정되어 있지 않으면 GNU 는 종료하기 전에 패턴 공간을 인쇄 합니다. 이 선택은 의도적으로 설계된 것입니다.
예를 들어, 동작은 sed N foo bar
foo에 짝수 줄 또는 홀수 줄이 있는지에 따라 다릅니다. 또는 패턴 일치 다음에 나오는 다음 몇 줄을 읽도록 스크립트를 작성할 때 기존의 구현 에서는 just 대신에 sed
무언가를 작성해야합니다 ./foo/{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N }
/foo/{ N;N;N;N;N;N;N;N;N; }
어쨌든 가장 간단한 해결 방법은 $d;N
기존 동작에 의존하는 스크립트 에서 사용 하거나 POSIXLY_CORRECT
변수를 비어 있지 않은 값 으로 설정하는 것 입니다.
POSIXLY_CORRECT
환경 변수가 언급 POSIX의 경우되도록 지정하기 때문에 sed
시도 할 때 만남이를 끝까지 N
가 출력없이 종료해야하지만,이 경우에는 표준 GNU 버전 의도적으로 바꿈. 또한 동작이 정당화되었다고 가정하더라도 오류 사례는 전체 파일을 메모리로 슬러 핑하지 않고 스트림 편집 중 하나라는 것입니다.
표준 을 정의 N
의 행동을 따라서 :
이 노트에서 다른 GNU-isms, 특히 :
레이블, b
목장 및 {
함수 문맥 괄호 사용과 같은 문제가 시연되었습니다 }
. 경험상 sed
임의의 매개 변수를 허용하는 명령 \n
은 스크립트 의 ewline에서 구분하는 것으로 이해됩니다 . 명령은 ...
:arbitrary_label_name; ...
b to_arbitrary_label_name; ...
//{ do arbitrary list of commands } ...
... sed
읽는 구현 에 따라 모두 불규칙하게 수행 될 가능성이 높습니다 . 그것들은 다음과 같이 작성되어야합니다.
...;:arbitrary_label_name
...;b to_arbitrary_label_name
//{ do arbitrary list of commands
}
동일은 마찬가지이다 r
, w
, t
, a
, i
,과 c
(그리고 아마도 내가 지금 잊고있는 몇 가지 더) . 거의 모든 경우에 다음과 같이 작성 될 수도 있습니다.
sed -e :arbitrary_label_name -e b\ to_arbitary_label_name -e \
"//{ do arbitrary list of commands" -e \}
새 -e
xecution 문은 \n
ewline 분리 문자 를 나타냅니다 . 따라서 GNU info
텍스트에서 전통적인 sed
구현 방식은 다음과 같이 강제합니다 .
/foo/{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N }
오히려 ...
/foo/{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N
}
물론 그것은 사실이 아닙니다. 그런 식으로 스크립트를 작성하는 것은 약간 바보입니다. 동일한 작업을 수행하는 훨씬 더 간단한 방법이 있습니다.
printf %s\\n foo . . . . . . |
sed -ne 'H;/foo/h;x;//s/\n/&/3p;tnd
//!g;x;$!d;:nd' -e 'l;$a\' \
-e 'this is the last line'
... 인쇄
foo
.
.
.
foo\n.\n.\n.$
.$
this is the last line
... t
대부분의 sed
명령 과 마찬가지로 est 명령도 리턴 레지스터를 새로 고치는 라인주기에 따라 달라 지기 때문에 여기서 라인주기는 대부분의 작업을 수행 할 수 있습니다. 그것은 파일을 쓸 때 또 다른 절충점입니다. 라인 사이클이 다시 새로 고쳐지지 않으므로 많은 테스트가 비정상적으로 작동합니다.
위의 명령은 읽을 때 읽은 내용을 확인하기 위해 간단한 테스트를 수행하기 때문에 입력에 도달 할 위험이 없습니다. 로 H
된 모든 라인은 보류 영역에 추가됩니다하지만 라인이 일치하는 경우 /foo/
는 덮어 h
오래된 공간. 다음에 버퍼가 x
변경 s///
되고 버퍼의 내용이 //
마지막으로 처리 된 패턴 과 일치하면 조건부 폐기가 시도됩니다 . 다른 단어에서 //s/\n/&/3p
시도 자체 보류 공간에서 세 번째로 줄 바꿈을 교체하고 결과를 인쇄하는 경우 보류 공간은 일치합니다 /foo/
. 이 t
스크립트가 성공하면 스크립트는 n
ot d
elete 레이블로 분기됩니다.이 레이블은 l
ook을 수행하고 스크립트를 마무리합니다.
두하는 경우 /foo/
및 제 3 개행 후, 그래도 유지 공간에서 서로 일치시킬 수없는 //!g
경우에는 버퍼를 덮어 /foo/
일치하지 않거나,이 일치하는 경우 경우,이 버퍼를 덮어 \n
ewline가 일치하지 하여 대체 ( /foo/
하여 자체) . 이 작은 미묘한 테스트는 버퍼를 오랫동안 채우지 않아도 불필요하게 채워 /foo/
지지 않도록하고 입력이 쌓이지 않기 때문에 프로세스가 빠르게 유지되도록합니다. no /foo/
또는 //s/\n/&/3p
fail 경우에 이어 버퍼가 다시 스왑되고 모든 행이 있지만 마지막 행이 삭제됩니다.
마지막 줄 $!d
- 마지막 줄 은 sed
여러 사례를 쉽게 처리하기 위해 하향식 스크립트 를 만드는 방법을 간단히 보여줍니다 . 가장 일반적인 방법으로 시작하여 가장 구체적인 방법으로 작업하는 원치 않는 사례를 제거하는 일반적인 방법 인 경우, 원하는 다른 데이터를 사용하여 스크립트의 끝까지 넘어갈 수 있기 때문에 엣지 사례를보다 쉽게 처리 할 수 있습니다. 원하는 데이터 만 남게됩니다. 그러나 닫힌 루프에서 이러한 엣지 케이스를 가져와야하는 것은 훨씬 더 어려울 수 있습니다.
그리고 마지막으로 말해야 할 것이 있습니다. 만약 당신이 정말로 전체 파일을 가져와야한다면, 줄주기에 의존하여 당신을 위해 약간의 일을 할 수 있습니다. 일반적으로 N
ext 및 n
ext는 선순환 보다 앞서 있기 때문에 미리보기에 사용 합니다. 회선주기가 단순한 읽기 루프 이기 때문에 루프 내에서 폐쇄 루프를 중복 구현하는 대신 목적이 입력을 무차별 적으로 수집하는 것이라면 다음과 같이하는 것이 더 쉽습니다.sed
sed 'H;1h;$!d;x;...'
... 전체 파일을 수집하거나 파산하려고합니다.
N
마지막 행 동작 에 대한 참고 사항 ...
테스트 할 도구가 없지만 편집 한 파일이 다음 판독을위한 스크립트 파일 인 N
경우 읽고 편집 할 때 내부 편집이 다르게 동작 한다는 점을 고려 하십시오.