다음을 사용하여 파일 끝에만 있는 빈 줄을 모두 제거하고 싶습니다.awk
다음 명령을 사용하여 상단의 빈 줄을 모두 제거하는 방법을 성공적으로 찾을 수 있었습니다.
awk '/^$/ && a!=1 {a=0} !/^$/ {a=1} a==1 {print}' file.txt
그러나 결론을 제거할 수 있도록 반전시키는 방법을 모르겠습니다. 위의 명령을 사용하여 파이프로 연결할 수 있다는 것을 알고 있지만 가능하다면 tac
명령을 사용하는 직접적인 접근 방식을 선호합니다 .awk
명확히 하자면, "시각적으로 비어 있는" 줄, 즉 최대 공백 및/또는 탭을 포함하는 줄은 "빈" 것으로 간주됩니다.
답변1
앗
awk는 외부 도움(예: Tac) 없이 첫 번째 줄부터 마지막 줄까지 순차적으로 파일을 읽기 때문에 실제로 파일 끝에 도달했을 때 빈 줄 블록이 파일 끝에 있는지 여부만 알 수 있습니다.
당신이 할 수 있는 일은 빈 줄(예: 개행 문자, 기본 레코드 구분 기호 RS
)이 있는 변수를 유지하고 비어 있지 않은 줄에 도달하면 해당 빈 줄을 인쇄하는 것입니다.
awk '/^$/{n=n RS}; /./{printf "%s",n; n=""; print}' file
print n
왜 와 사이에 차이가 있는지 이해가 되지 않습니다printf n
.
print
출력 레코드 구분 기호 추가( ORS
, 기본값은 개행)을 인쇄할 표현식으로 설정합니다. 따라서 시도하면 추가 개행 문자를 얻게 됩니다. 다음과 같이 단일 출력 문을 사용하여 작성할 수도 있습니다.
awk '/^$/{n=n RS}; /./{printf "%s%s%s",n,$0,RS; n=""}' file
에드또는전임자
출력을 인쇄하려면(Awk와 마찬가지로) 다음 옵션 중 하나를 선택하십시오.
printf '%s\n' 'a' '' '.' '?.?+1,$d' ',p' 'Q' | ed -s file
printf '%s\n' 'a' '' '.' '?.?+1,$d' '%p' 'q!' | ex -s file
변경 사항을 파일에 직접 적용하려면 다음 옵션 중 하나를 선택하세요.
printf '%s\n' 'a' '' '.' '?.?+1,$d' 'w' 'q' | ed -s file
printf '%s\n' 'a' '' '.' '?.?+1,$d' 'x' | ex -s file
명령 대체
쉘은 명령 대체에서 후행 개행을 제거합니다.
printf '%s\n' "$(cat file)"
일부 쉘은 대용량 파일을 처리할 수 없으며 "인수 목록이 너무 김" 오류를 발생시킵니다.
에서 영감을 받다이 답변.
답변2
이 1단계 접근 방식은 입력이 파이프에서 나오든 파일에서 나오든 관계없이 작동하지만 빈 줄의 각 블록은 메모리에 저장되어야 합니다(입력에 수십억 개의 연속 빈 줄이 없으면 실제로 작동하지 않을 수 있음). ) 질문) ):
awk 'NF{print s $0; s=""; next} {s=s ORS}' file
이 2단계 접근 방식은 입력이 파이프인 경우에는 작동하지 않지만, 입력이 질문에서 말하는 것과 같은 파일이고 메모리를 거의 사용하지 않는 경우에는 작동하지 않습니다.
awk 'NR==FNR{if (NF) n=NR; next} FNR>n{exit} 1' file file
위의 내용에서는 공백만 포함된 줄이 "비어 있는" 줄로 간주된다고 가정합니다. 이것이 잘못된 경우 NF
로 변경하십시오 /./
.
답변3
awk 'length == 0 { ++n; next } { for (i = 1; i <= n; ++i) print ""; n = 0 }; 1' file
또는 댓글에 제안된 대로 줄이세요.
awk 'length == 0 { ++n; next } { while (n) { print ""; --n } }; 1'
이것은 counter 에서 빈 라인의 실행을 추적합니다 n
.
빈 줄( length == 0
)이 보일 때마다 카운터는 증가하지만 아무것도 인쇄되지 않습니다.
비어 있지 않은 줄이 보이면 먼저 현재 줄 앞에 적절한 수의 빈 줄을 출력하십시오. 카운터 n
도 재설정됩니다.
이렇게 하면 파일 끝에서 빈 줄이 출력되는 것을 방지할 수 있습니다.
사용 표준 sed
:
sed -n -e :again -e N -e '/[^\n]/!b again' -e p file
이는 버퍼에 줄바꿈 이외의 내용이 있을 때까지 버퍼에 줄을 추가하는 명시적인 루프를 도입합니다. 이 시점에서 버퍼가 출력됩니다. read 를 사용하는 동안 입력 파일이 종료되면 N
버퍼의 데이터(개행만)가 출력되지 않습니다.
주석 처리된 코드(처음에는 #n
을 사용하는 것과 마찬가지로 기본 출력을 끕니다 -n
):
#n
# Label to branch to later.
:again
# Append next line of input to buffer
# with a delimiting newline.
N
# Branch (jump) to :again if there's
# only newlines in the buffer.
/[^\n]/!b again
# Output buffer.
p
답변4
co=`awk '!/^$/{x=NR}END{print x}' filename`
co=$(($co+1))
j="$co,$"
sed -i "${j}d" filename
테스트를 거쳐 잘 작동함