친애하는 내가 가진 모든 것큰데이터 파일은 말할 수 있습니다파일.dat, 두 개의 열이 포함되어 있습니다
예: file.dat(몇 개의 행 표시)
0.0000 -23.4334
0.0289 -23.4760
0.0578 -23.5187
0.0867 -23.5616
0.1157 -23.6045
0.1446 -23.6473
0.1735 -23.6900
0.2024 -23.7324
0.2313 -23.7745
0.2602 -23.8162
0.2892 -23.8574
0.3181 -23.8980
0.3470 -23.9379
0.3759 -23.9772
0.4048 -24.0156
0.4337 -24.0532
0.4627 -24.0898
0.4916 -24.1254
note: data file has a blank line at the end of the file
예상되는 결과
예를 들어 열-1과 같이 두 열 모두에서 최대값과 최소값을 찾거나 추출하고 싶습니다.
max - 0.4916
min - 0.0000
마찬가지로 열 -2
max - -23.4334
min - -24.1254
불완전한 솔루션(열 2에서는 작동하지 않음)
열-1의 경우
awk 'BEGIN{min=9}{for(i=1;i<=1;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
0.0000
cat file.dat | awk '{if ($1 > max) max=$1}END{print max}'
0.4916
열 2의 경우
awk 'BEGIN{min=9}{for(i=2;i<=2;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
-23.4334
cat file.dat | awk '{if ($2 > max) max=$2}END{print max}'
**no output showing**
문제
열 2의 최소값과 최대값을 찾는 데 도움을 주세요. 참고: 데이터 파일 끝에는 빈 줄이 있습니다.
답변1
코드의 문제,
awk 'BEGIN{min=9}{for(i=2;i<=2;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
exit
... 첫 번째 입력 줄을 처리한 직후 입니다 . 중간 블록이 트리거되어야 합니다.모든선. 그런 다음 END
찾은 값을 블록에서 인쇄할 수 있습니다. 다른 코드 조각에서 이 작업을 수행합니다.
awk '{if ($1 > max) max=$1}END{print max}'
또 다른 문제는 min
매직 넘버(인용한 첫 번째 코드에서는 9, 두 번째 부분에서는 0, 명시적으로 초기화되지 않은 변수는 계산에 사용하는 경우 값이 0임)로 초기화한다는 것입니다. 이 매직 넘버가 실제 데이터의 숫자 범위에 속하지 않으면 계산된 최소값 및/또는 최대값이 잘못됩니다. min과 max를 모두 데이터에서 발견된 값으로 초기화하는 것이 좋습니다.
추적하려면둘 다최소 및 최대 값을 사용하려면 두 개의 변수가 필요하며, 이 두 변수는 업데이트가 필요한지 확인하기 위해 모든 줄에 대해 파일의 데이터와 비교하여 확인해야 합니다.
배열을 지원 하므로 및 열당 배열 요소가 하나씩 있는 awk
배열을 사용하는 것이 자연스럽습니다 . 이것이 제가 아래 코드에서 수행한 작업입니다.min
max
임의 개수의 열로 일반화됨:
NF == 0 {
# Skip any line that does not have data
next
}
!initialized {
# Initialize the max and min for each column from the
# data on the first line of input that has data.
# Then immediately skip to next line.
nf = NF
for (i = 1; i <= nf; ++i)
max[i] = min[i] = $i
initialized = 1
next
}
{
# Loop over the columns to see if the max and/or min
# values need updating.
for (i = 1; i <= nf; ++i) {
if (max[i] < $i) max[i] = $i
if (min[i] > $i) min[i] = $i
}
}
END {
# Output max and min values for each column.
for (i = 1; i <= nf; ++i)
printf("Column %d: min=%s, max=%s\n", i, min[i], max[i])
}
이 스크립트와 질문의 데이터를 고려하면 다음과 같습니다.
$ awk -f script.awk file
Column 1: min=0.0000, max=0.4916
Column 2: min=-24.1254, max=-23.4334
모든 라인에 대해 실행되는 첫 번째 블록의 조건 NF == 0
은 빈 라인을 건너뛰는 것입니다. 테스트는 "이 줄에 데이터 필드(열)가 0개인 경우"를 의미합니다. 변수는 initialized
처음부터 0이 됩니다(논리적으로거짓)이지만 1로 설정됩니다(논리적으로는진실) 데이터가 있는 첫 번째 줄을 읽자마자.
변수 는 및 값을 초기화하는 줄의 (필드 수) nf
로 초기화됩니다 . 이는 마지막 줄에 필드가 0인 경우에도 블록 의 출력이 작동하도록 하기 위한 것입니다 .NF
min
max
END
답변2
실제로 모든 지침을 하나의 awk
프로그램으로 결합할 수 있습니다.
awk 'NR==1{min1=max1=$1;min2=max2=$2}\
NR>1 {if ($1<min1) {min1=$1} else if ($1>max1) {max1=$1};\
if ($2<min2) {min2=$2} else if ($2>max2) {max2=$2}; }\
END{printf("Column1 min: %f\nColumn1 max: %f\nColumn2 min: %f\nColumn2 max:%f\n",min1,max1,min2,max2)}' file.dat
그러면 첫 번째 행의 각 값(조건이 있는 규칙 NR==1
)을 사용하여 두 열의 최소값과 최대값이 초기화되고, 연속 행을 스캔하여 값이 각각 현재 최대값보다 큰지/현재 최소값보다 작은지 확인합니다. (조건이 있는 규칙 NR>1
).
파일 끝(조건이 있는 규칙 END
)에서 결과를 인쇄합니다.
알아채다이것이 가정하는 것빈 줄이 없습니다. 있는 경우 NR>1
조건을 로 바꿔야 합니다 NR>1 && NF>0
. 빈 줄이 있을 수 있는 경우첫 번째 전에, 사용
awk '!init && NF>0 {init=1; min1=max1=$1; min2=max2=$2} \
init==1 && NF>0 {if ($1<min1) {min1=$1} else if ($1>max1) {max1=$1};\
if ($2<min2) {min2=$2} else if ($2>max2) {max2=$2}; }\
END{printf("Column1 min: %f\nColumn1 max: %f\nColumn2 min: %f\nColumn2 max:%f\n",min1,max1,min2,max2)}' file.dat
이는 변수를 사용하여 init
비어 있지 않은 줄이 이미 발견되었는지 확인하고 비어 있지 않은 첫 번째 줄의 내용을 사용하여 두 열의 현재 최대/최소값을 미리 설정합니다. init
이 초기화 이후에 설정된 경우에만 해당 통계를 입력할 때 (비어 있지 않은) 행이 고려됩니다.
일반적으로 cat
파일을 만들고 결과를 awk
.
답변3
사용datamash
그리고 printf
:
for f in 1 2 ; do printf 'Column #%s\nmax - %s\nmin - %s\n\n' $f \
$(datamash -W max $f min $f < file.dat); done
...또는 루프 없이:
printf 'Column #%s\nmax - %s\nmin - %s\n\n' \
$(datamash -W max 1 min 1 max 2 min 2 < file.dat |
tr -s '\t' '\n' | paste - - | nl)
다음 중 하나의 출력:
Column #1
max - 0.4916
min - 0
Column #2
max - -23.4334
min - -24.1254
답변4
이것은 열 1에 대한 것입니다(평균 최대값과 최소값을 계산합니다).
sort -n -k 1 file |awk '{SUM+=$1 ; if ( NR == 1) MIN=$1} END{print "Average - "SUM/NR, "Min time - "MIN,"Max Time - "$1}'
이것은 2열에 대한 것입니다
sort -n -k 2 file |awk '{SUM+=$1 ; if ( NR == 1) MIN=$1} END{print "Average - "SUM/NR, "Min time - "MIN,"Max Time - "$1}'