다음 데이터 세트가 끝날 때까지 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
답변2
접근 방식의 문제점은 블록 print
에 명령문이 하나만 있다는 것입니다 END
. 이 블록의 값은 $0
파일의 마지막 줄 내용입니다. 따라서 awk
코드는 파일의 마지막 줄만 인쇄합니다.
또한 awk
작업을 다음에 적용한다는 점에 유의하세요.각 라인블록 앞에 조건이 없는 경우 { ... }
(예: END
파일 끝에만 적용됨) 따라서 코드는 첫 번째, 세 번째 등을 확인하려고 시도합니다.대지~의각 라인또는이면 3
각각 또는로 바꾸십시오 4
. 그러나 결과는 인쇄하지 마십시오.0
1
모든 홀수 행에 규칙을 적용하려면 해당 행 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