Арифметика между двумя файлами, создающая серию новых файлов с использованием awk

Собственныйiso9660 не поддерживает файлы размером более 2 ГБ . Вместо этого вам нужно использовать iso9660 :1988 , добавив опцию -level 3к вашей команде.

человек 8 mkisofs:

-iso-level level

...

With level 3, no restrictions (other than ISO-9660:1988) do apply

....

0
22.03.2021, 18:57
2 ответа

л.с.; DR:Компактный 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 ).

Если указать меньше полей, чем множителей, избыточные множители просто игнорируются.

В любом случае поля всегда используют множители в порядке номера строки, в которой они появляются, т. е. первое поле, обнаруженное во входном файле, использует первый множитель, независимо от того, как вы указали поле.

1
28.04.2021, 22:58

Использование Perl для создания выходных файлов.

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
1
28.04.2021, 22:58

Теги

Похожие вопросы