(를 사용하여) 파일의 시작과 끝에서 빈 줄을 제거하는 방법을 찾는 동안 tac
다음을 발견했습니다.
awk 'NF {p=1} p'
이것이 어떻게/왜 작동하나요?
필드가 있는 경우(행이 빈 행이 아닌 경우) NF
만 이해합니다 .true
답변1
이렇게 하면 처음부터 빈 줄이 제거됩니다.하지만 끝부터가 아니야파일의.[참고: 이 답변은질문 수정언급됨 tac
]
작동 방식은 다음과 같습니다.
NF
현재 행에서 발견된 필드 수입니다. 0이면 행이 비어 있거나공백즉, 최대 공백을 포함합니다(필드 구분 기호가 기본값으로 남아 있다고 가정하고 연속 공백의 수는 구분 기호로 간주됩니다).{ ... }
규칙 블록 외부(및 연관되지 않음)의 조건이 로 평가되면 현재 행을 인쇄합니다true
. 이 플래그는p
처음에는 초기화되지 않고 로 평가되므로false
사전에 아무 것도 인쇄되지 않습니다.- 비어 있지 않은 줄이 발견되면(
NF
0이 아니고 로 평가됨true
) 규칙 블록을 입력{p=1}
하고p
플래그를 로 설정합니다1
. 그 후에는p
규칙 블록 외부가 로 평가되고true
모든 후속 행(현재 비어 있지 않은 첫 번째 행 포함)이 인쇄됩니다.
알아채다이 플래그는 p
재설정되지 않으므로 비어 있지 않은 첫 번째 줄 이후의 모든 빈 줄은 필터링 없이 인쇄됩니다. 끝에서 빈 줄도 제거하려면 2단계 접근 방식을 수행해야 합니다.
awk 'FNR==NR{if (NF) {if (!first) first=FNR; last=FNR} next}
FNR>=first && FNR<=last' input.txt input.txt
그러면 파일이 두 번 처리됩니다(따라서 피연산자로 두 번 지정됨).
- 각 파일 라인 카운터가 전역 라인 카운터
FNR
와 동일한 첫 번째 패스에서는 비어 있지 않은 첫 번째 라인과 마지막 라인을 식별합니다.NR
- 두 번째 패스(
FNR
이제 보다 작음NR
)에서는 식별된 첫 번째 줄과 비어 있지 않은 마지막 줄 사이의 줄만 인쇄합니다.
알아채다
에서 언급했듯이Stephen Chazeras의 답변, 2단계 방법은 일반 파일에만 작동합니다. 입력 내용이 성격이 다른 경우 여기에 제안된 솔루션에 대한 접근 방식을 참조하세요.
답변2
파일의 시작과 끝에서 빈 줄을 제거하려면 이 기술을 사용하십시오.
awk 'NF {p=1} p' file | # remove blank lines at the file head
tac | # reverse the lines
awk 'NF {p=1} p' | # remove blanks from the "new head"
tac | # re-reverse the file
sponge file # from the `moreutils` package, to overwrite the file
답변3
코드의 기능과 입력 시작 부분의 빈 줄만 제거하는 이유는 이미 설명되어 있습니다.@AdminBee의 답변예를 들어, 완전성을 기하기 위해 파일을 두 번 통과할 필요 없이 앞뒤의 빈 줄을 제거하는 대체 방법을 제안하겠습니다(이 방법은 임의 입력이 아닌 일반 파일에서만 작동합니다).
awk '
NF {print saved $0; saved = ""; started = 1; next}
started {saved = saved $0 ORS}' < file
이후에 볼 수 있는 비어 있지 않은 다음 줄이 나올 때까지 빈 줄의 인쇄를 지연합니다(이전에 비어 있지 않은 줄을 하나 이상 본 적이 있는 경우).
답변4
유지하려는 빈 줄에서 공백이나 탭을 분리해도 괜찮다면 시작과 끝의 빈 줄이 제거됩니다.
awk 'NF{for(;c;--c)print "";print;x=1;next} x{++c}'
비어 있지 않은 줄 사이에 나타나는 빈 줄 수를 계산하고 비어 있지 않은 각 줄 앞에 해당 개수의 빈 줄을 인쇄합니다.