awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A B
awk: 명령. 줄: 1: (FILENAME=A FNR=18) 치명적: 0으로 나누기를 시도했습니다.
이 오류를 해결하는 데 도움을 줄 수 있는 사람이 있나요?
NR==1
여기서 합계는 무엇을 NR>1
의미하나요? 그것은 이상한 예에 있습니다. 나는 그것을 이해하지 못합니다. NR이 레코드 번호인 것은 알지만 여기서는 왜 사용합니까?
답변1
예제 작성자는 파일 A와 B를 다음 형식으로 상상한 것 같습니다.
파일 A:
X Y Z
1 2 3
4 5 6
파일 B:
6 7 8
o o 0
AWK 예제에서는 네 번째 열을 생성합니다. 여기서 NR은 현재 AWK에서 처리 중인 행을 나타냅니다. 첫 번째 줄에서는 네 번째 인수를 문자열 "ratio"(열 이름)로 설정하고, 모든 후속 줄에서는 네 번째 인수를 두 번째 인수로 나눈 세 번째 인수로 설정합니다. 결과:
awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A
X Y Z ratio
1 2 3 1.5
4 5 6 1.2
6 7 8 1.14286
1 2 3 1.5
발생한 오류는 다음과 같습니다.
awk: 명령. 줄: 1: (FILENAME=A FNR=18) 치명적: 0으로 나누기를 시도했습니다.
파일 A의 18행에 2열과 3열의 숫자가 포함되어 있는지 확인하세요.
sed를 사용하여 'o' 문자를 0으로 변환할 수 있습니다.
cat A B | sed 's/\bo\b/0/g'
열 2가 0인지 확인하고 그에 따라 조치를 취할 수 있습니다.
awk 'NR==1{$4="ratio"}NR>1{if($2==0) $4 = "N/A"; else $4 = ($3)/($2)}
합치면 다음과 같은 이점을 얻을 수 있습니다.
cat A B | sed 's/\bo\b/0/g' | awk 'NR==1{$4="ratio"}NR>1{if($2==0) $4 = "N/A"; else $4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}'
X Y Z ratio
1 2 3 1.5
4 5 6 1.2
6 7 8 1.14286
0 0 0 N/A
답변2
주어진 예에서,
awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A B
NR
지금까지 읽은 레코드 수입니다. 다음과 같은 예에서 이를 사용하여 다음과 같이 테이블 헤더를 건너뛸 수 있습니다.
Date Cost Quantity
2016/04/10 12.57 3
2016/04/19 11.74 2
왜냐하면 "비용"을 "수량"(숫자가 아님)으로 나눌 수 없기 때문입니다.
그건 그렇고, 당신의 데이터할 수 있다4개 이상의 열이 있습니다. 그러나 awk를 사용하면 입력 데이터에 없는 열에 할당할 수 있습니다. 따라서 처음에는 $4="ratio"
기존 열을 변경하는 것일 수도 있지만 연속 레코드에 대한 계산을 반영하기 위해 데이터에 열을 추가하는 것일 가능성이 높습니다.
오류(0으로 나누기)의 해석은 다른 질문입니다 NR
. 숫자 데이터가 있는지 확인 $2
하고 $3
패턴을 사용할 수 있습니다. 예를 들어 다음 확인을 추가하세요.
다음과 같은 것을 생산합니다
#!/bin/sh
awk 'function isnum(v) {
if ( v ~ /^[0-9.]+$/ )
return 1;
else
return 0;
}
(NR==1){$4="ratio"}
(NR>1 && NF >= 3 && isnum($2) && isnum($3) && $3 > 0){$4 = ($3)/($2)}
{print $1 "\t" $2 "\t" $3 "\t" $4}' A B
이 isnum
함수는 단순화되었지만 부호 없는 소수를 허용합니다.
한 줄 스크립트를 선호한다면 awk 스크립트는 자유 형식이라는 점을 기억하세요. 그래서... 이렇게 할 수 있습니다:
awk 'function isnum(v){if(v~/^[0-9.]+$/)return 1;else return 0;}(NR==1){$4="ratio"}(NR>1&&NF>=3&&isnum($2)&&isnum($3)&&$3>0){$4=($3)/($2)}{print $1"\t"$2"\t"$3"\t"$4}' A B