2つのファイル間の算術演算により、一連の新しいファイルが生成されます(パート2)

2つのファイル間の算術演算により、一連の新しいファイルが生成されます(パート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

以下のように、ディストリビューションでランダムに選択された乗数ファイルが1行に1つずつあります。

cat multipliers.txt

0.1
0.5
0.25

あるフィールド(wsg)に2番目のファイルの単一の乗数を掛ける一連の新しい入力ファイルを作成したいと思います。この例では、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番目のフィールド(この場合は3番目(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 {直前に追加するだけです。

おすすめ記事