한 열의 최소값과 최대값을 찾고 다른 열의 해당 값을 찾습니다.

한 열의 최소값과 최대값을 찾고 다른 열의 해당 값을 찾습니다.

이것은 내 샘플 텍스트 파일입니다.

[s]            [K]        
1              900
2              100 
3              200
8              1000
1              80
55             12
6              90000
5              1

열 2에서 최대값을 찾고 열 1에서 해당 값을 찾은 다음 열 1의 모든 요소에서 해당 값을 빼야 합니다.

내가 원하는 출력은 이것이다

[s]            [K]        
-5              900
-4              100 
-3              200
2              1000
-5              80
49             12
0              90000
-1              1

이건 내 단편이야

awk 'function abs(x) {return x<0?-x:x}
FNR==1  { $1=$1; print; next }
{if(max<$2){max=$2;line=$1}}{print $1-line "\t"$2}' test.txt

어쨌든 이것은 나에게 올바른 결과를 제공하지 않습니다. 또한 열 2의 가장 작은 값이 동일한 값을 갖기를 원합니다.

답변1

데이터를 두 번 통과해야 하며, 먼저 최소값과 최대값을 찾은 다음 계산을 수행해야 합니다.

awk 'BEGIN { OFS = "\t" }
     FNR == NR { if (FNR > 1 && (min == "" || $2 < min)) { min = $2; minval = $1 }
                 if (FNR > 1 && (max == "" || $2 > max)) { max = $2; maxval = $1 }
                 next }
     FNR == 1 { print "[s (-max)]", "[s (-min)]", "[K]"; next }
              { print $1 - maxval, $1 - minval, $2 }' file file

주어진 데이터에 대해 다음이 생성됩니다.

[s (-max)]      [s (-min)]      [K]
-5      -4      900
-4      -3      100
-3      -2      200
2       3       1000
-5      -4      80
49      50      12
0       1       90000
-1      0       1

awk코드에는 4개의 블록이 있으며 여기에 입력 파일을 전달합니다.두 배. 첫 번째 블록( BEGIN)은 단순히 출력 필드 구분 기호를 탭으로 설정합니다.

두 번째 블록( )은 파일을 처음 통과하는 동안 각 행에 대해 실행되며 두 번째 열( sum ) 의 최대값과 최소값 및 첫 번째 열( sum ) 의 해당 값을 FNR == NR추적합니다 . 필요에 따라 업데이트합니다 . 이 블록의 끝에서 현재 입력된 스크립트의 나머지 부분을 건너뛰는 데 사용됩니다.maxminmaxvalminvalnext

NR현재 레코드의 전체 시퀀스 번호("줄 번호") FNR이지만 현재 파일의 번호와 같습니다. 입력 파일을 처음으로 전달할 때와 동일합니다 NR.FNR

FNR == 1세 번째 블록( )은 두 번째 패스 파일에서 첫 번째 라인을 읽었을 때 실행됩니다. 제목만 출력합니다. 첫 번째 열의 값 minval에서 합계 값을 뺀 값을 계산하므로 새 열 머리글을 추가합니다.maxval

마지막 블록은 무조건적이며 파일을 두 번째로 통과하는 동안 두 번째 줄을 실행하고 데이터의 실제 계산과 출력을 수행합니다.

다음과 같이 파이프하면 약간 더 예쁜 출력을 얻을 수 있습니다 column -s $'\t' -t.

[s (-max)]  [s (-min)]  [K]
-5          -4          900
-4          -3          100
-3          -2          200
2           3           1000
-5          -4          80
49          50          12
0           1           90000
-1          0           1

답변2

$ cat tst.awk
BEGIN { OFS="\t" }
NR==1 { next }
NR==2 { maxVal = $2 }
NR==FNR {
    if ($2 >= maxVal) {
        maxSth = $1
        maxVal = $2
    }
    next
}
{ print (FNR>1 ? ($1 - maxSth) : $1) , $2 }

$ awk -f tst.awk file file
[s]     [K]
-5      900
-4      100
-3      200
2       1000
-5      80
49      12
0       90000
-1      1

답변3

어쩌면 이런 게 있지 않을까요?로그 처리 파일을 두 번.

awk 'NR==FNR && NR>1 { max_col2=( max_col2>$2?max_col2:$2 ); max[$2]=$1;  
                       min_col1=( min_col1>$1?min_col1:$1 ); min[$1]=$2; }
     NR!=FNR && FNR>1{ print $1-max[max_col2], $2-min[min_col1]; }' OFS='\t' infile infile
-5      888
-4      88
-3      188
2       988
-5      68
49      0
0       89988
-1      -11

관련 정보