나는 이것을 가지고있다:
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:
이걸 설명해야 하니까...
이것은 불필요하게 복잡합니다. 그래서 "빈 줄 제거" 를 {}
다른 방식으로 표현해야 합니다. 핵심 명령은 t
sed가 수행하는 방식 입니다 if ... then
. T
더 쉬웠을 것이지만 GNU sed에만 해당됩니다. 나는 매뉴얼 페이지를 인용하고 있습니다 :
t label : 마지막 입력 행을 읽은 이후 as///가 성공적으로 대체된 경우 label로 분기하고 label이 생략된 경우 마지막 t 또는 T 명령 이후로 스크립트 끝으로 분기합니다.
나는 그 유명한 s
명령을 남용했습니다. 아무것도 대체하지 않고 해당 줄이 비어 있는지 테스트만 합니다. 따라서 빈 줄을 빈 줄로 바꿉니다(어차피 줄이 삭제되므로 무엇이든 대체물로 사용할 수 있습니다).
s
"교체"가 완료되면 행이 비어 있습니다 . 이 경우 d
명령을 실행해야 합니다. 그렇지 않으면 아무것도 할 수 없습니다. t
액션을 실행하는 동안 점프가 없기 때문에 스크립트 끝으로 점프하려면 s
분기 명령이 필요합니다 . 지점 대상입니다. 암흑시대(sed가 발명되었을 때... 테히) 처럼요 .b
: label
goto
또 다른 옵션은 s
비어 있지 않은 모든 줄을 "대체"하여 s
명령을 더 복잡하게 만들고 나머지는 더 쉽게 만드는 것입니다.
sed '5,${s/^\(..*\)$/\1/; t end; d; : end;}' input
^..*$
이는 "공백이 아닌 줄"을 의미하며 \1
"첫 번째 괄호의 내용"을 의미합니다.