일련의 새 파일을 생성하기 위해 awk를 사용하여 두 파일 사이의 산술

일련의 새 파일을 생성하기 위해 awk를 사용하여 두 파일 사이의 산술

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

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)와 동일한 일련의 새 입력 파일을 생성하려고 합니다. 이 경우 첫 번째 파일에는 vox_la_max, knockout_max, shed_prob2, 3, 4, 두 번째 파일에는 3, 2, 2, 세 번째 파일에는 4, 3, 3을 곱하고 싶습니다 . 아래와 같이 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를 사용해야 할 것 같은데 지금까지는 열 승수 파일을 사용하여 한 번에 하나의 매개변수만 성공적으로 변경할 수 있었고 동시에 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이 비트는 로케일에서 부동 소수점 값의 소수 구분 기호로 점 대신 쉼표를 사용하는 경우 필요합니다.

단순화를 위해 합리적으로 보이는 몇 가지 가정을 세웠습니다.

  • 필수 입력 필드는 항상 필드 이름이 한 단어이고 공백(최소 하나의 공백)으로 구분되어야 함을 나타내는 주석이 인접한 별도의 값입니다./*
  • 같은 이름의 필드가 없습니다.
  • 부동 소수점 값은 숫자와 (아마도) 점으로만 표현됩니다. 즉, 지수나 기타 과학적 표현은 사용하지 않습니다.

위와 동일하지만 다음을 허용하도록 상세하고 설명되고 확장되었습니다.

  • 행 번호별로 필수 항목을 임의로 지정
  • 각 필드에 속하는 입력 라인의 주석으로 참조되는 이름으로 필수 필드를 임의로 지정합니다.
  • 출력 파일은 확장자(예: .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을 곱함)이 됩니다.

승수보다 적은 수의 필드를 지정하면 초과 승수는 무시됩니다.

어떤 경우든 필드는 항상 표시된 줄 번호 순서대로 승수를 사용합니다. 즉, 입력 파일에서 발견된 첫 번째 필드는 해당 필드를 지정하는 방법에 관계없이 첫 번째 승수를 사용합니다.

답변2

사용진주출력 파일을 생성합니다.

perl -wMstrict -pale '
BEGIN {
  ## variables declaration
  use vars qw($name $extn);
  use vars qw($header $template $footer);
  use vars qw(@glob_params $num_re);

  ## pick apart include.txt filename into its components
  ($name, $extn) =
    pop =~ m{(.*?)(\.[^.]*|)$}x;

  ## split and stuff into variables the include.txt file
  ($header, $template, $footer) =
    do{local $/;<STDIN>;} =~
    m{\A
    (.*?\n)
    (\#+\h*GENERAL\h+PARAMETERS\h*\n.*?\n\n)
    (.*)
    }xms;

  ## names of global parameters to vary
  @glob_params =
    qw( vox_la_max knockout_max shed_prob);

  # cinstruct the regex to search for numbers
  my $sign = qr{ [-+] }x;
  my $float = qr{ \d+(?:\.\d*)?|\.\d+ }x;
  my $exponent = qr{ [eE][-+]?\d+ }x;
  $num_re =
    qr{ $sign? $float $exponent? }x;
}

##### multiplier.txt processed from here onwards
  my %mult;
  @mult{ @glob_params } = @F;
  my $template_copy = $template;
  for (@glob_params) {
    $template_copy =~
      s{^($num_re)(?=\h+/\*\h*\Q$_\E\b)}{$1 * $mult{$_}}xme;
  }

  my $out = sprintf "%s%d%s",
    $name, $., $extn;
  open my $fh, ">", $out
    or die "Opening $out for writing:$!";
  select $fh;
  s/.*/$header$template_copy$footer/;
' multipliers.txt < include.txt include.txt

관련 정보