Как извлечь несколько значений из файла за один проход?

Для этого можно использовать следующий скрипт. Из вашего вопроса непонятно, как именно вы определяете «основной» файл для каждого входного файла. В приведенном ниже сценарии предполагается, что это единственный другой файл в папке.

#!/usr/bin/env bash

while IFS= read -r f  # every line is represented by $f
do
    d=$(dirname "$f") # $f's directory
    b=$(basename "$f") # $f's basename
    bwoe=${b%.*} # $f's basename without extension
    m=$(find "$d" -mindepth 1 -maxdepth 1 -not -name "$b" | head -n 1) # get first file in the folder that is not $f
    m=$(basename "$m") # basename of main file
    printf "%s\\t%s\\t%s\\n" "$f" "$bwoe" "$m"
done < input.txt # input.txt contains the input scripts

Пример:

$ ls a b c
a:
afoo.sh  a.sh

b:
bmain.sh  b.sh

c:
c.sh  cxx.sh
$ cat input.txt 
a/a.sh
b/b.sh
c/c.sh
$ bash script.sh 
a/a.sh  a       afoo.sh
b/b.sh  b       bmain.sh
c/c.sh  c       cxx.sh
6
21.11.2020, 16:59
6 ответов
sed -n '/^Max/ { s/^.*=\s*//;h; };
        /^Time/{ s/^.*=\s*//;G; s/\n/ /;p; }' infile
  • соответствие -синтаксис запуска/.../{... }:
    команды в {...}будут выполняться только в строках, соответствующих регулярному выражению/шаблону в /.../;

  • s/^.*=\s*//:
    удаляет все от -до последнего =и пробелы \s*также, если они были.

  • h:
    скопируйте результат в пробел -

  • G:
    добавить пробел -к пробелу шаблона -со встроенной новой строкой

  • s/\n/ /:
    замените эту встроенную новую строку пробелом в шаблоне -пробел

  • p:
    шаблон печати -пробел; вместо этого вы можете использовать команду P.

    0.000001 3.0355
    0.000013 4.3644
    0.000025 3.7319
    1.32125 7.0695
    

Похожий подход, предложенный @stevesliva , который используется s//<replace>/в качестве сокращения для выполнения подстановки в последнем совпадении:

sed -n '/^Max.*=\s*/ { s///;h; };
        /^Time.*=\s*/{ s///;G; s/\n/ /;p; }' infile
10
18.03.2021, 22:48

Я не могу гарантировать, что это будет быстрее, но вы можете сделать что-то подобное в awk:

awk -F' = ' '$1=="Max value of omega" {omega = $2} $1=="Time" {print omega,$2}' file
7
18.03.2021, 22:48
$ awk 'BEGIN{print "#time", "omega"} /^Max value of omega =/{omega=$NF; next} /^Time =/{print $NF, omega}' file
#time omega
0.000001 3.0355
0.000013 4.3644
0.000025 3.7319
1.32125 7.0695

но это, вероятно, будет быстрее:

$ grep -E '^(Max value of omega|Time) =' file |
    awk 'BEGIN{print "#time", "omega"} NR%2{omega=$NF; next} {print $NF, omega}'
#time omega
0.000001 3.0355
0.000013 4.3644
0.000025 3.7319
1.32125 7.0695
5
18.03.2021, 22:48

Что-то вроде

paste \
  <(<file awk -F= '$1 ~ /omega/ {print $2}') \
  <(<file awk -F= '$1 ~ /Time/ {print $2}')

Думаю даже

<file grep -o '[[:digit:].]*' | paste - -

Или

<file cut -d= -f2 | paste - -

Подойдет

0
18.03.2021, 22:48

grep может искать несколько шаблонов за один раз

-e PATTERNS, --regexp=PATTERNS
Use PATTERNS as the patterns. If this option is used multiple times or is combined with the -f (--file) option, search for all patterns given. This option can be used to protect a pattern beginning with “-”.

Итак,

grep -F -e 'Max value of omega = ' -e 'Time = ' logfile

уменьшит размер области поиска. Затем вы можете опубликовать процесс с одним из других предложений.

0
18.03.2021, 22:48

альтернативным, возможно, более простым решением sed было бы

sed -nr 'N;s/^Max value of omega = ([0-9.]+)\nTime = ([0-9.]+)$/\1 \2/p;D;' logfile

где 'N' добавляет вторую строку в пространство шаблонов, блок 's/pattern/string/p' ищет двухстрочный шаблон и выводит две группы захвата (\1 \2 ), разделенные символом пробел, и, наконец, D отбрасывает первую строку из пространства шаблонов.

Одним из преимуществ этого подхода, который я использовал в прошлом при поиске многострочных -шаблонов, является то, что вы можете распечатать группы захвата в произвольном порядке, не обязательно в том порядке, в котором они появляются в файле. Так что в вашем примере, если вам нужно «Время» в первом столбце, вы можете просто сделать это

sed -nr 'N;s/^Max value of omega = ([0-9.]+)\nTime = ([0-9.]+)$/\2 \1/p;D;' logfile

Обратите внимание, что теперь здесь написано «\2 \1», а не «\1 \2».

0
18.03.2021, 22:48

Теги

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