一連の新しいファイルを生成するためにawkを使用して2つのファイル間の算術

一連の新しいファイルを生成するためにawkを使用して2つのファイル間の算術

次のように、統合分析形式に変更したいタブ区切りのモデル入力ファイルがあります。

cat input.txt
#############################################   
###  Parameter file for the program ### 
#############################################   
### GENERAL PARAMETERS
4   /* nbout # Number of outputs */ 
46  /* numesp # Number of species */
0.05    /* p # light incidence param (diff through turbid medium) */
0.1357158   0.2446549   0.3535940   0.4992873   0.6449806   0.6957850   0.7465893   0.8130218   0.8794543   0.9397271   1.0000000   0.9397271   0.8794543   0.8078294   0.7362045   0.6899817   0.6437589   0.5989616   0.5541642   0.4617186   0.3692730   0.3633708   0.3574686   0.2426215   /* normalized daily light course (from 7am to 7pm, with a half-hour time-step */
1   /* vox_la_max. The max voxel leaf area. */
0   /* l_growth_scheme. 0 = top down; 1 = random; 2 = homogeneous; 3 = bottom up */
0.1 /* knockout_max. Parameter controlling the extent to which lianas can knock out trees */
0.05    /* shed_prob. With this probability, the liana is completely shed from the voxel. */

### Species description                                 
****    Nmass   LMA wsg dmax    hmax    ah  tmax    seedmass    Fregdistgr  Pmass   g1  s_liana
Alvaradoa_amorphoides   0.0214  74.775  0.584   0.5 24.44   0.892   1   0.0078  40  0.00145 3.77    0
Annona_reticulata   0.0350  74.529  0.503   0.5 24.44   0.892   1   0.2392  40  0.00142 3.77    0
Brosimum_alicastrum 0.0201  104.281 0.760   0.5 17.31   0.117   1   1.2486  40  0.00097 3.77    0

### Climate (input environment)
25.47447    26.02723    26.87827    27.58436    26.95839    25.63987    25.61669    25.26543    24.99990    24.10808    24.71997    24.67287    /*Temperature in degree C*/

次の形式のディストリビューションで、タブ区切りの別の乗数ファイルを選択しました。

cat multipliers.txt
2   3   4
3   2   2
4   3   3

3つの特定の入力フィールドに乗数を掛けて、残りの入力ファイルは変更せずに乗数(この場合は3)と同じ一連の新しい入力ファイルを生成しようとします。この場合、最初のファイルには、、2、3、4、2番目のファイルには3、2、2、3番目のファイルにvox_la_maxknockout_max4、3、3shed_probを掛けたいと思います。以下のように3つの新しいファイルを作成します。

cat input1.txt
#############################################   
###  Parameter file for the program ### 
#############################################   
### GENERAL PARAMETERS
4   /* nbout # Number of outputs */ 
46  /* numesp # Number of species */
0.05    /* p # light incidence param (diff through turbid medium) */
0.1357158   0.2446549   0.3535940   0.4992873   0.6449806   0.6957850   0.7465893   0.8130218   0.8794543   0.9397271   1.0000000   0.9397271   0.8794543   0.8078294   0.7362045   0.6899817   0.6437589   0.5989616   0.5541642   0.4617186   0.3692730   0.3633708   0.3574686   0.2426215   /* normalized daily light course (from 7am to 7pm, with a half-hour time-step */
2   /* vox_la_max. The max voxel leaf area. */
0   /* l_growth_scheme. 0 = top down; 1 = random; 2 = homogeneous; 3 = bottom up */
0.3 /* knockout_max. Parameter controlling the extent to which lianas can knock out trees */
0.2 /* shed_prob. With this probability, the liana is completely shed from the voxel. */

### Species description                                 
****    Nmass   LMA wsg dmax    hmax    ah  tmax    seedmass    Fregdistgr  Pmass   g1  s_liana
Alvaradoa_amorphoides   0.0214  74.775  0.584   0.5 24.44   0.892   1   0.0078  40  0.00145 3.77    0
Annona_reticulata   0.0350  74.529  0.503   0.5 24.44   0.892   1   0.2392  40  0.00142 3.77    0
Brosimum_alicastrum 0.0201  104.281 0.760   0.5 17.31   0.117   1   1.2486  40  0.00097 3.77    0

### Climate (input environment)
25.47447    26.02723    26.87827    27.58436    26.95839    25.63987    25.61669    25.26543    24.99990    24.10808    24.71997    24.67287    /*Temperature in degree C*/
cat input2.txt
#############################################   
###  Parameter file for the program ### 
#############################################   
### GENERAL PARAMETERS
4   /* nbout # Number of outputs */ 
46  /* numesp # Number of species */
0.05    /* p # light incidence param (diff through turbid medium) */
0.1357158   0.2446549   0.3535940   0.4992873   0.6449806   0.6957850   0.7465893   0.8130218   0.8794543   0.9397271   1.0000000   0.9397271   0.8794543   0.8078294   0.7362045   0.6899817   0.6437589   0.5989616   0.5541642   0.4617186   0.3692730   0.3633708   0.3574686   0.2426215   /* normalized daily light course (from 7am to 7pm, with a half-hour time-step */
3   /* vox_la_max. The max voxel leaf area. */
0   /* l_growth_scheme. 0 = top down; 1 = random; 2 = homogeneous; 3 = bottom up */
0.2 /* knockout_max. Parameter controlling the extent to which lianas can knock out trees */
0.1 /* shed_prob. With this probability, the liana is completely shed from the voxel. */

### Species description                                 
****    Nmass   LMA wsg dmax    hmax    ah  tmax    seedmass    Fregdistgr  Pmass   g1  s_liana
Alvaradoa_amorphoides   0.0214  74.775  0.584   0.5 24.44   0.892   1   0.0078  40  0.00145 3.77    0
Annona_reticulata   0.0350  74.529  0.503   0.5 24.44   0.892   1   0.2392  40  0.00142 3.77    0
Brosimum_alicastrum 0.0201  104.281 0.760   0.5 17.31   0.117   1   1.2486  40  0.00097 3.77    0

### Climate (input environment)
25.47447    26.02723    26.87827    27.58436    26.95839    25.63987    25.61669    25.26543    24.99990    24.10808    24.71997    24.67287    /*Temperature in degree C*/
cat input3.txt
#############################################   
###  Parameter file for the program ### 
#############################################   
### GENERAL PARAMETERS
4   /* nbout # Number of outputs */ 
46  /* numesp # Number of species */
0.05    /* p # light incidence param (diff through turbid medium) */
0.1357158   0.2446549   0.3535940   0.4992873   0.6449806   0.6957850   0.7465893   0.8130218   0.8794543   0.9397271   1.0000000   0.9397271   0.8794543   0.8078294   0.7362045   0.6899817   0.6437589   0.5989616   0.5541642   0.4617186   0.3692730   0.3633708   0.3574686   0.2426215   /* normalized daily light course (from 7am to 7pm, with a half-hour time-step */
4   /* vox_la_max. The max voxel leaf area. */
0   /* l_growth_scheme. 0 = top down; 1 = random; 2 = homogeneous; 3 = bottom up */
0.3 /* knockout_max. Parameter controlling the extent to which lianas can knock out trees */
0.15    /* shed_prob. With this probability, the liana is completely shed from the voxel. */

### Species description                                 
****    Nmass   LMA wsg dmax    hmax    ah  tmax    seedmass    Fregdistgr  Pmass   g1  s_liana
Alvaradoa_amorphoides   0.0214  74.775  0.584   0.5 24.44   0.892   1   0.0078  40  0.00145 3.77    0
Annona_reticulata   0.0350  74.529  0.503   0.5 24.44   0.892   1   0.2392  40  0.00142 3.77    0
Brosimum_alicastrum 0.0201  104.281 0.760   0.5 17.31   0.117   1   1.2486  40  0.00097 3.77    0

### Climate (input environment)
25.47447    26.02723    26.87827    27.58436    26.95839    25.63987    25.61669    25.26543    24.99990    24.10808    24.71997    24.67287    /*Temperature in degree C*/

awkを使用する必要があるようですが、これまでは列乗数ファイルを使用して一度に1つのパラメータのみを正常に変更でき、同時に3つのパラメータをすべて変更できる必要があります。これらの出力を生成するためにどのようなスクリプトを設定できますか?

ベストアンサー1

TL;博士:awkあなたの例のためにハードコードされた圧縮スクリプト

NR != FNR {
    out = "out" FNR ".txt"
    printf "" > out
    for (l=m=1; l <= nl; l++)
        printf tmpl[l] ORS, l in vals ? $(m++)*vals[l] : 0 >> out
    close(out)
    next
}

{
    gsub(/%/, "%%")
# here is the regex that selects the fields by their name
    if ($3 ~ /^(vox_la_max|knockout_max|shed_prob)[^[:alnum:]_]*$/) {
        vals[NR] = $1
        sub(/^[0-9]+(\.[0-9]+)?/, OFMT)
    }
    tmpl[NR] = $0; nl++
}

次のように使用してください。

LC_NUMERIC=C awk -f script input.txt multipliers.txt

という出力ファイルが生成されますoutX.txt

LC_NUMERIC=Cこのビットは、ロケール内の浮動小数点値の小数点区切りとしてドットの代わりにコンマを使用する場合に必要です。

単純化のために合理的に見えるいくつかの仮定を確立しました。

  • 必須入力フィールドは、常にフィールド名が1つの単語であり、スペース(少なくとも1つのスペース)で区切る必要があることを示すコメントが隣接する別々の値です。/*
  • 同じ名前のフィールドはありません。
  • 浮動小数点値は、数値と (おそらく) 点で表現されます。つまり、指数や他の科学的表現は使用しません。

上記と同じですが、以下を可能にするために詳細、説明、拡張されました。

  • 行番号別に必須項目を任意に指定
  • 各フィールドに属する入力行のコメントとして参照される名前で、必須フィールドをランダムに指定します。
  • 出力ファイルは拡張子(例:.txt)を持つことができる入力ファイル名に沿って自動的に名前が付けられ、表示されるパス(存在する場合)は次のようになります。いいえつまり、入力ファイルが含まれているディレクトリでスクリプトを実行することをお勧めします。
# some preparations
BEGIN {
    # output files named as the input file name
    split(ARGV[1], f, ".")
    outpfx = f[1]
    # remember wanted fields specified on command line as comma-separated line numbers
    if (nums) {
        # split variable "nums" on comma into helper array "r"
        n = split(nums, r, ",")
        # loop over helper array to build final array, thus indexed by wanted line numbers
        while (n) rows[r[n--]]
    }
}

# here we operate on multipliers file
NR != FNR {
    # output file name for this set of multipliers
    out = outpfx FNR ".txt"
    # create/overwrite this output file
    printf "" > out
    # loop over template lines scanned from input file
    for (linenum = multnum = 1; linenum <= numlines; linenum++)
        # use the template line as printf format string to consume values to be multiplied (if any)
        printf tmpl[linenum] ORS, linenum in wanted_values ? $(multnum++)*wanted_values[linenum] : 0 >> out
    close(out)
    next
}

# here we scan the input file to build a template for printf
{
    # escape existing % chars as we are going to leverage printfs own format string which is %-based
    gsub(/%/, "%%")
    # on specified line numbers or named fields:
    if (NR in rows || names && match($3, "^("names")[^[:alnum:]_]*$")) {
        # remember this value
        wanted_values[NR] = $1
        # replace the original value with the printfs conversion specification for floating-point values
        # it will be used by printf later on while processing the multipliers file
        sub(/^[0-9]+(\.[0-9]+)?/, OFMT)
    }
    # remember this whole line as a template
    tmpl[NR] = $0; numlines++
}

次のように使用してください。

# specify fields by their line numbers, each separated by a comma
LC_NUMERIC=C awk -f script -v nums=36,38,39 input.txt multipliers.txt
# or specify fields by their names, each separated by the | character (NOTE it's a regexp)
LC_NUMERIC=C awk -f script -v names='vox_la_max|knockout_max|shed_prob' input.txt multipliers.txt
# or also use both ways of specifying fields
LC_NUMERIC=C awk -f script -v nums=15,112,234,71,5 -v names='vox_la_max|numesp' input.txt multipliers.txt

乗数よりも多くのフィールドが指定されている場合、超過フィールドは0(0を掛けます)になります。

乗数よりも少ないフィールドを指定すると、超過乗数は無視されます。

いずれにせよ、フィールドは常に表示された行番号順に乗数を使用します。つまり、入力ファイルで見つかった最初のフィールドは、そのフィールドの指定方法に関係なく、最初の乗数を使用します。

おすすめ記事