아래 목록에 표시된 것처럼 수천 개의 행이 있습니다.
파일명="텍스트 파일"
3 2 3 1 4 7
5 8 6 8 9 8
8 9 4 7 3 9
2 3 4 4 9 2
2 2 0 9 4 0
0 9 8 2 4 0
조건을 사용하여 특정 요소(예: 다섯 번째 열)를 검색해야 합니다. (실제로 최대값을 찾아야 합니다.) 이 출력을 원합니다. 다섯 번째 열의 최대값 = 9
라인: 5 8 6 8 9 8
2 3 4 4 9 2
다음 코드를 사용했습니다.
var=$(cat newfifth1 | awk 'BEGIN {max = 0} {if ($5>max) max = $5} END {print max}')
cat textfile | grep "$var" | cat $1 $2 $3 $4 $5 $6 >> newtextfile
하지만 작동하지 않습니다!
가능하다면 배열을 사용하는 더 쉬운 방법과 방법을 알려주십시오.
답변1
귀하의 질문에 있는 데이터 샘플에 따르면 이것이 귀하가 원하는 것 같습니다(그렇지 않으면 질문을 명확히 해주세요).
awk '$5 > max { max = $5 ; out = $0 } END { print out }' datafile
그러면 열 5에 최대값이 있는 데이터 파일의 행이 인쇄됩니다.
프로그램은 다음과 같이 작동합니다. 각 행에 대해 다섯 번째 열 요소를 max
저장된 최대값(초기 0)과 비교하고, 더 큰 값이 발견되면 max
할당된 값을 얻고(이후 비교를 위해) 현재 Row( $0
) 변수에 저장된 최대값을 포함합니다 out
. 프로그램의 마지막 작업으로 변수의 값이 out
인쇄됩니다.
데이터에 0보다 작은 값만 있는 경우 ( max
암묵적인 0 초기화로 인해) 약간의 확장이 필요합니다. 일반적으로 max
해당 값보다 낮은 것으로 알려진 값으로 변수를 명시적으로 초기화하는 것으로 충분합니다. 예 를 들어 BEGIN { max = -999999 }
다음과 같은 일반적인 코드 패턴을 사용할 수도 있습니다.
awk '(max==0 && max=="") || $5 > max { max = $5 ; out = $0 } END { print out }' datafile
(max==0 && max=="")
조건 부분을 " max
아직 정의되지 않았나요?"(즉, 아직 값이 할당되지 않음)로 해석합니다.
답변2
여기에는 몇 가지 해결책이 있습니다.
2회(무한 그룹):
awk '
{
if (NR == FNR) {
if ($5 > max) max = $5
} else {
if ($5 == max) print
}
}' textfile textfile
NR
모든 입력에서 계산된 레코드 번호(줄 번호)입니다.FNR
줄 번호입니다현재 파일 내에서. 따라서 예를 들어 3줄 길이의 와 4줄 길이의awk
2개 파일의 입력을 사용하여 실행하는 경우 다음 값이 사용됩니다.fileC
fileD
NR
FNR
NR FNR 1 1 2 2 3 3 4 1 5 2 6 3 7 4
따라서 테스트는
NR == FNR
첫 번째 파일이 표시되는지 확인하는 고전적인 방법입니다.- 따라서 위의 내용은 입력 파일을 두 번 읽습니다(두 번 지정된 마지막 줄을 보셨나요
textfile
?). 첫 번째 패스에서 최대값이 발견되면 두 번째 패스에서는 해당 값을 포함하는 모든 행을 인쇄합니다.
원샷(어레이 사용):
awk '
{
if ($5 >= max) {
if ($5 > max) {
max = $5
delete result
count = 0
}
result[++count] = $0
}
}
END { for (i = 0; i <= count; i++) print result[i] }' textfile
- 그러면 최대값과 일치하는 행이 라는 배열에 저장됩니다
result
. 파일 읽기를 마칠 때까지(파일을 한 번만 읽기 때문에) 최대값을 알 수 없기 때문에 이는 까다롭습니다. 따라서 이전에 본 것보다 높은 값(즉, 새로운 최대값을 찾는 경우)을 만날 때마다 배열을 지우고(delete
) 다시 시작합니다.result
- 그런 다음 파일 끝에 도달하면 찾은 내용을 인쇄합니다.
참고: 다섯 번째 열의 모든 값이 0 이하이면 위 명령이 실패합니다. 이 상황을 처리하려면 "전체"( 테스트 포함) if ($5 >…
로 변경하세요.if (max == "" || $5 >…
if ($5 >= max)