`awk 'NF {p=1} p'`는 어떻게 파일의 시작과 끝에서 빈 줄을 제거합니까?

`awk 'NF {p=1} p'`는 어떻게 파일의 시작과 끝에서 빈 줄을 제거합니까?

파일의 시작과 끝( 을 사용하여 tac)에서 빈 줄을 제거하는 방법을 검색하다가 다음을 발견했습니다.

awk 'NF {p=1} p'

이것이 어떻게/왜 작동하나요?

나는 필드가 있는 경우 NF에만 true(행이 빈 행이 아닌 경우) 이해합니다.

답변1

이렇게 하면 처음부터 빈 줄이 제거됩니다.하지만 끝에서부터는 아니야파일의.[참고: 이 답변은 이전에 기록되었습니다.질문 편집언급한 것 tac]

다음과 같이 작동합니다:

  • NF현재 행에서 발견된 필드 수입니다. 0이면 해당 줄이 비어 있거나공백즉, 최대 공백을 포함합니다(필드 구분 기호가 기본값으로 남아 있다고 가정하고 연속된 공백의 수는 구분 기호로 간주됩니다).
  • { ... }규칙 블록( ) 외부의(그리고 연관되지 않은) 조건이 로 평가 되면 현재 행이 인쇄됩니다 true. 플래그는 p처음에 초기화되지 않고 로 평가되므로 false선험적으로 아무것도 인쇄되지 않습니다.
  • 비어 있지 않은 줄이 발견되면( NF0이 아니고 로 평가됨 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)에서는 그렇게 식별된 첫 번째와 마지막 비어 있지 않은 줄 사이(및 포함)의 줄만 인쇄합니다.

알아채다

에 명시된 바와 같이답변: Stéphane Chazelas, 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}'

비어 있지 않은 줄 사이에 빈 줄이 몇 개 있는지 계산하고, 비어 있지 않은 각 줄 앞에 그 만큼의 빈 줄을 인쇄합니다.

관련 정보