Shell-Script

生成一系列新文件的 2 個文件之間的算術 (Pt 2)

  • February 15, 2021

這是對上一個問題(生成一系列新文件的 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 個欄位,在這種情況下是第 3 個(wsg)

剛剛重新閱讀了您的問題,我實際上建議您執行以下操作,這不依賴於您告訴它哪個欄位是該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 {行之前。

引用自:https://unix.stackexchange.com/questions/634648