awk: 새 레코드 생성 및 NR 업데이트

awk: 새 레코드 생성 및 NR 업데이트

해결해야 할 특정 문제보다는 일반적인 질문에 가깝습니다.

이런 파일이 있다고 가정 해 봅시다

entry 1
entry 3
entry 6

누락된 항목을 채우고 싶습니다 awk. 새 레코드를 삽입하고 NR을 업데이트할 수 있나요? 아이디어는 다음과 같습니다.

awk 'BEGIN {print "NR","line"
     $2!=NR {<create record> "entry",NR ; <repeat commands on same record>}
     {print NR,$0}' file

따라서 명령은 다음과 같습니다.

  • 새 레코드 삽입
  • 새 레코드에 대해 일치하는 NR을 제공하고 다음 레코드 번호를 업데이트하세요.
  • 조건을 다시 확인하는 기능(예: entry 6도달하면 생성해야 entry 4하지만 entry 5손실되었음을 인식해야 합니다. 따라서 기록된 조건을 다시 확인해야 함 entry 6)

원하는 출력

NR line
1  entry 1
2  entry 2
3  entry 3
4  entry 4
5  entry 5
6  entry 6

답변1

할 수 없다입력 파일의 한 단계에서 새 입력 레코드를 생성합니다. 새 입력 레코드를 생성한다는 것은 다음 코드를 의미합니다.

awk '
    {
        print $0
        magic to create a new record with contents "Foo"
    }
'

원래 레코드를 인쇄한 다음 "Foo"를 인쇄하는 무한 루프에 들어갑니다. 정의에 따라 awk는 각 입력 레코드에 대해 위 코드를 한 번 실행하기 때문입니다.

입력 레코드에서 나오든 내부적으로 생성되든 상관없이 문자열에서 코드를 실행할 수 있습니다. 예를 들면 다음과 같습니다.

awk '
    {
        prt($0)
        other stuff
        prt("Foo")
    }
    function prt(str) {
        print str
    }
'

그러나 이는 실제로 새로운 입력 레코드를 생성하는 것과는 다릅니다.

첫 번째 패스에서 임시 파일을 만들고 쓰는 2단계 접근 방식을 수행할 수도 있습니다. 그러면 두 번째 패스에서 임시 파일을 읽을 때 새로 인쇄된 문자열이 이제 입력 레코드로 나타납니다.

NR당신은 "그래도"의 의미를 과부하/남용하고 있습니다 . NR개수입니다입력하다읽은 기록과 개수를 인쇄하려고 합니다.산출인쇄된 기록은 완전히 다른 문제입니다. 내장된 변수는 없습니다 . 아래와 NR같이 엉망으로 만드는 대신 별도의 변수로 직접 추적하는 것이 쉽기 때문입니다 .onr

$ cat file
awk '
    BEGIN { print "NR", "onr", "line" }
    NR == 1 { val = $2-1 }
    {
        for (val++; val<$2; val++) {
            processString($1 FS val)
        }
        processString($0)
    }

    function processString(str) {
        print NR, ++onr, str
    }
' file
NR onr line
1 1 entry 13
2 2 entry 14
2 3 entry 15
3 4 entry 16
3 5 entry 17
3 6 entry 18

그러나 새로운 입력 레코드를 생성하는 것이 아니므로 (언제나처럼) 내장 변수의 값을 조정하려는 시도는 전혀 부적절합니다 NR. 대신 새 출력 레코드를 생성하고 이름이 지정된 사용자 정의 변수에서 총 출력 레코드 수를 추적합니다 onr.

NR출력 에 및를 추가하고 onr예제 입력을 다음과 같이 변경했습니다.

$ cat file
entry 13
entry 15
entry 18

실제로 3가지 별도의 데이터 항목이 사용된다는 점을 강조하는 것이 중요합니다.

  1. NR= 레코드 수를 입력하고,
  2. onr= 출력 레코드 수,
  3. val= 각 레코드에 대해 인쇄할 $2의 값

프로그램의 명확성, 응집력, 결합성, 유지 관리성 등을 위해 이들 중 어느 것에도 과부하가 걸리지 않는 것이 가장 좋습니다.

답변2

편집 + 경고

아래 댓글에서 언급했듯이 NR그렇습니다 FNR.정의에 따르면카운터기록을 입력하세요그러므로 변함없이 유지되어야 합니다. (인용하다:친구 매뉴얼) 제한 없이 조작할 수 있지만 아래 제안된 대로 이러한 값을 조작하지 마십시오! 이 답변은 경고로 남겨 두겠습니다.


좋습니다. Jeff Schaller, Romeo Ninov 및 fra-san의 의견 덕분에 다음이 작동합니다.

  • 수동으로 추가 NR하거나FNR
  • 적절하게 정의된 루프를 사용하세요 NR. /FNR

가능한 스크립트:

awk 'BEGIN {print "NR","line"}
     $2 > NR { for (NR; NR<$2; NR++) print NR,"entry "NR }
     {print NR,$0}' infile

입력 파일이 여러 개인 경우 올바른 번호 매기기를 보장하기 위해 다음 NR으로 대체됩니다 ( 올바른 합계를 보장하는 데 계속 사용될 수 있음).FNRNR++

이는 NR++업데이트를 시뮬레이션하는 NR반면 루프는 동일한 레코드에서 명령을 다시 실행하는 것을 시뮬레이션합니다(문의 의사 반대와 반대 ). 이는 전체적으로 일치하는 ( ) next을 사용하여 새로 생성된 레코드처럼 보이게 합니다 .NRFNR

관련 정보