Shell-Script
生成一系列新文件的 2 個文件之間的算術 (Pt 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 個欄位,在這種情況下是第 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 {
行之前。