Как извлечь части строки в переменные?

8

У меня есть строка из некоторого файла, как это:

attempting to create a 512^3 level (with Dirichlet BC) using a 16^3 grid of 32^3 boxes and 800 tasks...

Я хочу , чтобы извлечь 512^3, 16^3, 32^3и 800четыре числа от него и назначить их соответственно четыре переменных level, grid, boxesи tasksдля других целей.

Как я могу это сделать?

Юлонг Ао
источник
Да, первые три из них имеют формат a ^ b, а последний - просто обычное число.
Юлонг Ао

Ответы:

15

Bash может сопоставлять регулярные выражения с =~оператором в [[ ... ]]:

#! /bin/bash

line='attempting to create a 512^3 level (with Dirichlet BC) using a 16^3 grid of 32^3 boxes and 800 tasks...'
num='([0-9^]+)'
nonum='[^0-9^]+'
if [[ $line =~ $num$nonum$num$nonum$num$nonum$num ]] ; then
    level=${BASH_REMATCH[1]}
    grid=${BASH_REMATCH[2]}
    boxes=${BASH_REMATCH[3]}
    tasks=${BASH_REMATCH[4]}
    echo "Level $level, grid $grid, boxes $boxes, tasks $tasks."
fi
choroba
источник
2
Ничего себе, никогда не знал, что Баш может сделать что-то вроде этого :)
Эратиэль
К вашему сведению 1: при написании регулярного выражения напрямую не заключайте его в кавычки . Например [[ 'Example 123' =~ '([0-9]+)' ]], ложно, но [[ 'Example 123' =~ ([0-9]+) ]]работает как задумано.
Джонатан Х
К вашему сведению 2: захват не работает несколько раз. Например [[ '1_2_3' =~ ([0-9]) ]] && echo ${BASH_REMATCH[@]}только совпадения 1.
Джонатан Х
2

Использование awk:

awk '{print "level="$5"\n""grid="$12"\n""boxes="$15"\n""tasks="$18}' file     
level=512^3
grid=16^3
boxes=32^3
tasks=800
jasonwryan
источник
2

Если это вывод из программы / сценария, который вы написали, а текст является формульным (т.е. точно соответствует этому шаблону), вы можете просто использовать cut.

#!/bin/bash

$STRING='attempting to create a 512^3 level (with Dirichlet BC) using a 16^3 grid of 32^3 boxes and 800 tasks...'

level=$(echo $STRING | cut -d' ' -f5 -)
grid=$(echo $STRING | cut -d' ' -f12 -)
boxes=$(echo $STRING | cut -d' ' -f15 -)
tasks=$(echo $STRING | cut -d' ' -f18 -)
toxefa
источник
1

Если строка всегда имеет именно эту структуру, readможно сделать это в одной строке без внешних процессов:

read x x x x level x x x x x x grid x x boxes x x tasks x <<<"$line"

(также используя Herestring ). Это сохранит все слова, которые вас не интересуют x(игнорируются), и значения, которые вы хотели, в соответствующие переменные.

Майкл Гомер
источник