두 파일 간의 산술 연산으로 일련의 새 파일이 생성됩니다(2부)

두 파일 간의 산술 연산으로 일련의 새 파일이 생성됩니다(2부)

이는 이전 질문에 대한 보다 구체적인 후속 조치입니다(두 파일 간의 산술 연산으로 일련의 새 파일이 생성됩니다.).

다음과 유사한 통합 분석 형식으로 변경하려는 탭으로 구분된 모델 입력 파일이 있습니다.

cat input.txt

/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.5 1
abies_grandis 2.5 0.4 1
larix_occidentalis 1.5 0.3 1

아래와 같이 배포판에서 무작위로 선택된 승수 파일이 한 줄에 하나씩 있습니다.

cat multipliers.txt

0.1
0.5
0.25

한 필드(wsg)에 두 번째 파일의 단일 승수를 곱하는 일련의 새 입력 파일을 생성하고 싶습니다. 이 예에서는 3개의 승수에 대한 3개의 새 파일이 있습니다(실제 분석에는 1000개의 승수가 포함됩니다). 출력 파일은 다음과 같습니다.

(wsg * 0.1)cat file1.txt

/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.05 1
abies_grandis 2.5 0.04 1
larix_occidentalis 1.5 0.03 1

(wsg * 0.5)cat file2.txt

/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.25 1
abies_grandis 2.5 0.2 1
larix_occidentalis 1.5 0.15 1

(wsg*0.25)cat file3.txt

/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.125 1
abies_grandis 2.5 0.1 1
larix_occidentalis 1.5 0.075 1

이전 질문을 바탕으로 @EdMorton은 다음을 제안했습니다.

$ cat tst.awk
NR==FNR {
    if ( pastHdr ) {
        ++numLines
        wsg[numLines] = $NF
        sub(/[[:space:]][^[:space:]]+$/,"")
        rest[numLines] = $0
    }
    else {
        hdr = hdr $0 ORS
        if ( $1 == "***" ) {
            pastHdr = 1
        }
    }
    next
}
{
    out = "file" FNR ".txt"
    printf "%s", hdr > out
    for (lineNr=1; lineNr<=numLines; lineNr++) {
        print rest[lineNr], wsg[lineNr] * $0 > out
    }
    close(out)
}
$ awk -f tst.awk input.txt multipliers.txt

이것은 이전 문제에 대한 훌륭한 솔루션이지만 산술은 입력의 각 줄의 마지막 필드에서 수행됩니다. 각 행의 n번째 필드(이 경우 세 번째(wsg))를 처리하도록 수정하고 싶습니다.

답변1

질문을 다시 읽은 후 실제로 다음을 수행할 것을 제안합니다. 이는 어떤 필드가 해당 필드인지 알려주는 것이 아니라 wsg입력 파일에서 다음으로 시작하는 줄에서 해당 정보를 읽는 것입니다.***

$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==FNR {
    if ( tgtFldNr ) {
        lines[++numLines] = $0
    }
    else {
        hdr = hdr $0 ORS
        if ( /^\*\*\*/ ) {      # in case this line is not tab-separated
            split($0,f," ")
            for (i in f) {
                if ( f[i] == "wsg" ) {
                    tgtFldNr = i-1
                    break
                }
            }
        }
    }
    next
}
{
    mult = $1
    out = "file" FNR ".txt"
    printf "%s", hdr > out
    for (lineNr=1; lineNr<=numLines; lineNr++) {
        $0 = lines[lineNr]
        $tgtFldNr *= mult
        print > out
    }
    close(out)
}

$ awk -f tst.awk input.txt multipliers.txt

$ head file*
==> file1.txt <==
/* Preciptation in mm */
10      30      40      50      23

### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa        2       0.05    1
abies_grandis   2.5     0.04    1
larix_occidentalis      1.5     0.03    1

==> file2.txt <==
/* Preciptation in mm */
10      30      40      50      23

### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa        2       0.25    1
abies_grandis   2.5     0.2     1
larix_occidentalis      1.5     0.15    1

==> file3.txt <==
/* Preciptation in mm */
10      30      40      50      23

### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa        2       0.125   1
abies_grandis   2.5     0.1     1
larix_occidentalis      1.5     0.075   1

후손을 위한 원래 답변:

$ cat tst.awk
NR==FNR {
    if ( pastHdr ) {
        lines[++numLines] = $0
    }
    else {
        hdr = hdr $0 ORS
        if ( $1 == "***" ) {
            pastHdr = 1
        }
    }
    next
}
{
    tgtFldNr = (n ? n : NF)
    mult = $1
    out = "file" FNR ".txt"
    printf "%s", hdr > out
    for (lineNr=1; lineNr<=numLines; lineNr++) {
        $0 = lines[lineNr]
        $tgtFldNr *= mult
        print > out
    }
    close(out)
}

$ awk -v n=3 -f tst.awk input.txt multipliers.txt

$ head file*
==> file1.txt <==
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.05 1
abies_grandis 2.5 0.04 1
larix_occidentalis 1.5 0.03 1

==> file2.txt <==
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.25 1
abies_grandis 2.5 0.2 1
larix_occidentalis 1.5 0.15 1

==> file3.txt <==
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.125 1
abies_grandis 2.5 0.1 1
larix_occidentalis 1.5 0.075 1

-v n=<number>곱할 필드 수를 설정하지 않으면 이전 질문에서 원했던 것처럼 기본적으로 각 행의 마지막 필드를 곱하게 됩니다.

귀하의 질문 텍스트에서 귀하의 입력이 탭으로 구분되어 있다고 말했지만 귀하가 제공한 예에서는 그렇게 보이지 않습니다. 실제로 탭으로 구분된 경우 BEGIN { FS=OFS="\t" }스크립트 상단, 해당 NR==FNR {줄 바로 앞에 추가하면 됩니다.

관련 정보