해결해야 할 특정 문제보다는 일반적인 질문에 가깝습니다.
이런 파일이 있다고 가정 해 봅시다
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가지 별도의 데이터 항목이 사용된다는 점을 강조하는 것이 중요합니다.
NR
= 레코드 수를 입력하고,onr
= 출력 레코드 수,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
으로 대체됩니다 ( 올바른 합계를 보장하는 데 계속 사용될 수 있음).FNR
NR++
이는 NR++
업데이트를 시뮬레이션하는 NR
반면 루프는 동일한 레코드에서 명령을 다시 실행하는 것을 시뮬레이션합니다(문의 의사 반대와 반대 ). 이는 전체적으로 일치하는 ( ) next
을 사용하여 새로 생성된 레코드처럼 보이게 합니다 .NR
FNR