주문하다:

주문하다:

블록은 항상 00 PROGRAM으로 시작합니다.

XYZ로 끝나고 그 뒤에 빈 줄이 옵니다. XYZ는 이전 행 블록에도 나타나지만 이전 행 뒤에는 더 많은 데이터가 옵니다. 빈 줄 앞의 마지막 줄만 필요합니다. 내 의도와 일치하는 코드를 찾지 못했습니다. 이것이 누군가에게는 쉬운 대답이기를 바랍니다!

빈 줄 앞의 마지막 줄을 유지하고 싶습니다. 예를 들어:

000-12-22
AB1
00   PROGRAM
01   INQUIRY
03   XYZ
04   XYZ
blank line
LINE VALUE
00456

이 부분만 삭제하면 됩니다.

00   PROGRAM
01   INQUIRY
03   XYZ

답변1

이 유형의 범위는 다음과 같습니다.완벽한사용 사례 ex. 나는 가지고있다ex많이 썼다이 사이트에서는 스크립트 파일 편집을 위한 최고의 POSIX 도구입니다.

주문하다:

하나의 블록만 처리해야 하는 경우 다음을 사용하세요.

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt

여러 블록이 가능한 경우 다음을 사용하세요.

printf '%s\n' 'g/00 PROGRAM/.,/^$/-2d' x | ex file.txt

테스트하려면 %p다음을 대신 사용하세요 x.

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' %p | ex file.txt
printf '%s\n' 'g/00 PROGRAM/.,/^$/-2d' %p | ex file.txt

그러면 버퍼의 내용을 파일에 다시 저장하는 대신 전체 버퍼가 인쇄됩니다.


삽화:

[vagrant@localhost ~]$ cat file.txt 
000-12-22
AB1
00 PROGRAM
01 INQUIRY
03 XYZ
04 XYZ

LINE VALUE
00456
[vagrant@localhost ~]$ printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt 
[vagrant@localhost ~]$ cat file.txt 
000-12-22
AB1
04 XYZ

LINE VALUE
00456
[vagrant@localhost ~]$ 

설명 및 의견:

를 사용할 수 있지만 ex -c 'editingcommands' filename이것이 해결하는 것보다 더 많은 문제를 야기한다는 것을 발견했습니다. ex오류가 발생하면 종료하는 대신 사용자 입력을 기다리면서 정지됩니다. 또한 exPOSIX는 이를 수행할 수 있는 공통 기능을 보장하지 않기 때문에 이러한 방식으로 여러 명령을 전달하는 데 잠재적인 이식성 문제가 있습니다 .

대신 일반적으로 명령을 exfrom 으로 파이프합니다 printf. 이를 통해 여러 명령을 형식 문자열을 사용하여 %s\n쉽게 개행으로 구분할 printf수 있으며, 오류가 발생하는 경우(예: 파일의 마지막 줄보다 큰 줄을 편집하려고 하는 경우) 파일이 중단되지 않고 그대로 유지됩니다.

실제로 파일을 편집하기 전에 명령을 테스트하기 위해 %p마지막 명령으로 (전체 버퍼 인쇄)를 사용합니다. 그런 다음 명령을 약간 조정하고 원하는 정확한 파일 내용을 얻을 때까지 반복해서 실행할 수 있습니다. 결과에 만족하면 명령을 실행 %p하도록 변경합니다.x하나실제로 파일 변경 사항을 저장하는 데 더 많은 시간이 걸립니다.

이 질문에 대한 답으로 제가 내린 명령은 다음과 같습니다.

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt

이 명령은 다음과 같이 새 줄로 구분 된 printf세 개의 문자열을 인쇄합니다 ./00 PROGRAM/.,/^$/-2dx

[vagrant@localhost ~]$ printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x
/00 PROGRAM/
.,/^$/-2d
x
[vagrant@localhost ~]$ 

이 세 줄은 ex명령입니다.

ex명령 개요

명령은 ex주소(라인 기반)와 명령의 두 부분으로 구성됩니다.

주소가 하나만 있는 경우 커서는 해당 주소(해당 줄로 이동)로 이동합니다.

명령만 있는 경우 현재 행이 주소로 사용됩니다.

주소는 일반적으로범위— 주소, 쉼표, 다른 주소 순입니다. 첫 번째 주소부터 두 번째 주소까지의 모든 라인을 나타냅니다.

주소는 행 번호일 수 있지만 반드시 그럴 필요는 없습니다. "이 정규식과 일치하는 현재 줄 다음 줄"을 의미하는 검색 패턴일 수도 있습니다. 앞으로 검색할 수도 있고 뒤로 검색할 수도 있습니다.

foo"이 인스턴스 앞의 두 줄은 현재 줄 바로 앞의 인스턴스 뒤에 발생합니다"라는 주소를 쓸 수도 있습니다 . bar이것은 다음과 같습니다:?bar?/foo/-2

단계별로

명령 /00 PROGRAM/은 단지 주소이므로 "'00 PROGRAM' 패턴의 첫 번째 인스턴스로 커서를 이동하십시오"라는 의미입니다.

이 명령은 .,/^$/-2d두 부분으로 구성됩니다. 마지막은 d"삭제"를 의미하는 명령입니다. 이제 남은 것은 주소뿐이다.

첫 번째 문자 .는 현재 행을 나타내는 특수 주소입니다.

패턴은 빈 줄(줄의 시작 과 줄의 끝 ) /^$/에 대한 정규식입니다 . 이 경우 현재 커서 위치 다음의 빈 줄을 의미합니다.^$

-2이는 "두 줄 뒤로"를 의미합니다 .

글쎄요, 이것이 .,/^$/-2d의미하는 바는 "현재 줄에서 다음 빈 줄 위의 두 줄까지 줄을 삭제합니다."입니다.

x간단히 말해서, 버퍼 내용을 파일에 저장하고 편집기를 종료하십시오.


이것이 당신에게 도움이 되기를 바랍니다. ex매우 강력한 텍스트 편집 도구입니다. vi"비주얼 에디터"의 전신 입니다 . 모든 명령을 ex실행할 수도 있습니다.vi

답변2

수정된 질문에 답하세요

이 테스트 파일을 고려해 보겠습니다.

$ cat File2
000-12-22
AB1
00 PROGRAM
01 INQUIRY
03 XYZ
04 XYZ

LINE VALUE
00456

다음 명령을 시도해 보세요.

$ sed '/00 PROGRAM/,/^$/{/./{h;d}; x; p; x;}' File2
000-12-22
AB1
04 XYZ

LINE VA

루에 00456

원래 질문에 답하다

00 PROGRAM내가 올바르게 이해했다면 빈 줄이 포함된 줄로 시작하고 끝나는 여러 선취권 세트가 포함된 파일이 있는 것입니다 XYZ. 이 경우 다음을 시도하십시오.

sed -n '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/p}' file 

다음 예제 파일을 고려해보세요.

$ cat file
00 PROGRAM
some
XYZ discard this
data
XYZ keep this

other
00 PROGRAM
more
XYZ keep this also

end

이는 XYZ블록의 빈 줄 앞의 줄만 유지합니다 00 PROGRAM.

$ sed -n '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/p}' file 
XYZ keep this
XYZ keep this also

선택하다

아마도 그룹 외부의 모든 행을 유지하고, 일치하는 경우 그룹의 비어 있지 않은 마지막 행도 유지하고 싶을 것입니다 XYZ. 이 경우:

$ sed '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/!d}' file 
XYZ keep this
other
XYZ keep this also
end

관련 정보