awk for 루프를 사용하여 특정 행의 값 바꾸기

awk for 루프를 사용하여 특정 행의 값 바꾸기

다음 데이터 세트가 끝날 때까지 1행, 3행, 5행 등의 모든 필드에서 값 3과 4를 각각 0과 1로 바꾸고 싶습니다.

 2 4 3 0
 2 4 3 0
 3 0 4 4
 3 0 4 4
 4 2 4 3
 4 2 4 3
 2 3 4 2
 2 3 4 2

따라서 원하는 결과는 다음과 같습니다.

 2 1 0 0
 2 4 3 0
 0 0 1 1
 3 0 4 4
 1 2 1 0
 4 2 4 3
 2 0 1 2
 2 3 4 2

이를 위해 다음 코드를 사용하고 있습니다.

awk '{for (i = 1; i <= NR; i=(i+2)) 
    if($i == 3) {$i = 0}
    if($i == 4) {$i = 1} 
}
END {print $0}' b.temp

그러나 이 코드의 출력은 b.temp 파일의 마지막 줄(2 3 4 2)에 있는 값뿐입니다.

어떻게 해야 하나요? 코드는 행과 필드 수에 제한이 없어야 합니다. 해결책은 awk, sed 또는 쉘 스크립트의 다른 대안일 수 있습니다.

미리 감사드립니다

답변1

sed를 사용하세요:

sed 'y/34/01/;n' file

의미는 다음과 같습니다

  • 이 줄의 3과 4를 0과 1로 바꾸고 인쇄합니다.
  • 다음 줄을 가져와서 인쇄하세요.
  • 다음 행을 가져와 루프를 반복합니다.

그러나 데이터에 (예: 14)가 포함된 경우 11로 변환하면 실패합니다. 이 문제를 해결하려면 다음을 선택하세요.

sed 's/\<4\>/1/g;s/\<3\>/0/g;n' file

이러한 \<and는 \>단어의 시작과 끝과 일치합니다.

답변2

접근 방식의 문제점은 블록 print에 명령문이 하나만 있다는 것입니다 END. 이 블록의 값은 $0파일의 마지막 줄 내용입니다. 따라서 awk코드는 파일의 마지막 줄만 인쇄합니다.

또한 awk작업을 다음에 적용한다는 점에 유의하세요.각 라인블록 앞에 조건이 없는 경우 { ... }(예: END파일 끝에만 적용됨) 따라서 코드는 첫 번째, 세 번째 등을 확인하려고 시도합니다.대지~의각 라인또는이면 3각각 또는로 바꾸십시오 4. 그러나 결과는 인쇄하지 마십시오.01

모든 홀수 행에 규칙을 적용하려면 해당 행 NR%2이 1인지(또는 단순히 0이 아닌지) 확인할 수 있습니다.

awk 'NR%2{for (i=1;i<=NF;i++) if ($i==3 || $i==4) $i-=3}1' b.temp

1규칙 외부에 나타날 때 awk"수행된 모든 변환의 결과 줄을 인쇄합니다."를 줄여서 표시 합니다.

답변3

내가 시도한보다 최적화 된 명령은 다음과 같습니다.

주문하다

awk 'NR==1||NR==3||NR==5||NR==7{gsub("3","0",$0)}1' file | awk 'NR==1||NR==3||NR==5||NR==7{gsub("4","1",$0)}1'

산출

 2 1 0 0
 2 4 3 0
 0 0 1 1
 3 0 4 4
 1 2 1 0
 4 2 4 3
 2 0 1 2
 2 3 4 2

관련 정보