5번째 줄부터 빈 줄을 제거하는 방법

5번째 줄부터 빈 줄을 제거하는 방법

나는 이것을 가지고있다:

sed -i '/^$/d' temp_spec.rb

이것은 빈 줄을 제거하고 훌륭하게 작동합니다. 5-999행(또는 파일 끝의 5행)에 대해서만 이 작업을 수행하려면 어떻게 해야 합니까?

나는 시도했다:

sed -n5,999 -i '/^$/d' temp_spec.rb
sed '5,999!d/^$/d' temp_spec.rb

하지만 둘 다 작동하지 않습니다(오류 없음).

답변1

5행부터 시작하여 모든 빈 행을 제거하고 1~4행을 유지하려면 다음을 사용할 수 있습니다.

sed -i '5,${;/^$/d;}' temp_spec.rb

{그룹화 연산자이므로 첫 번째 명령은 " 일치할 때까지 5,${5행부터 input( ) 끝까지 $다음 명령을 실행합니다 }"를 의미합니다. {와 사이의 명령에는 }주소가 앞에 붙을 수도 있으므로 내부 명령은 " /^$/d줄의 시작( )과 끝( ) 사이에 아무것도 없으면 삭제한다"는 의미입니다. sed 명령은 구분될 수 있습니다. (이것은 sed의 제대로 문서화되지 않은 기능입니다. 대부분의 sed 구현은 이를 지원하지만^$;완전히 휴대 가능하지는 않음.) Hauke가 지적했듯이 ;후자 {는 선택 사항이지만 전자 }는 필수입니다.

5행에서 시작하는 모든 빈 행을 삭제하고 1~4행을 삭제하려면 다음이 더 쉽습니다.

sed -i '1,4d;/^$/d' temp_spec.rb

답변2

awk를 사용하는 또 다른 옵션:

awk 'NR<5||/./'

답변3

sed '5,${s/^$//; t delete; b end; : delete; d; : end;}' temp_spec.rb

편집 1:

이걸 설명해야 하니까...

이것은 불필요하게 복잡합니다. 그래서 "빈 줄 제거" 를 {}다른 방식으로 표현해야 합니다. 핵심 명령은 tsed가 수행하는 방식 입니다 if ... then. T더 쉬웠을 것이지만 GNU sed에만 해당됩니다. 나는 매뉴얼 페이지를 인용하고 있습니다 :

t label : 마지막 입력 행을 읽은 이후 as///가 성공적으로 대체된 경우 label로 분기하고 label이 생략된 경우 마지막 t 또는 T 명령 이후로 스크립트 끝으로 분기합니다.

나는 그 유명한 s명령을 남용했습니다. 아무것도 대체하지 않고 해당 줄이 비어 있는지 테스트만 합니다. 따라서 빈 줄을 빈 줄로 바꿉니다(어차피 줄이 삭제되므로 무엇이든 대체물로 사용할 수 있습니다).

s"교체"가 완료되면 행이 비어 있습니다 . 이 경우 d명령을 실행해야 합니다. 그렇지 않으면 아무것도 할 수 없습니다. t액션을 실행하는 동안 점프가 없기 때문에 스크립트 끝으로 점프하려면 s분기 명령이 필요합니다 . 지점 대상입니다. 암흑시대(sed가 발명되었을 때... 테히) 처럼요 .b: labelgoto

또 다른 옵션은 s비어 있지 않은 모든 줄을 "대체"하여 s명령을 더 복잡하게 만들고 나머지는 더 쉽게 만드는 것입니다.

sed '5,${s/^\(..*\)$/\1/; t end; d; : end;}' input

^..*$이는 "공백이 아닌 줄"을 의미하며 \1"첫 번째 괄호의 내용"을 의미합니다.

관련 정보