Como extrair partes de uma string para variáveis?

8

Eu tenho uma linha de algum arquivo como este:

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

Eu quero extrair o 512^3, 16^3, 32^3e 800quatro números a partir dele e atribuir-lhes, respectivamente, para quatro variáveis level, grid, boxese taskspara outro uso.

Como posso fazer isso?

Yulong Ao
fonte
Sim, os três primeiros têm o formato a ^ be último apenas o número usual.
Yulong Ao 16/04

Respostas:

15

O Bash pode corresponder expressões regulares ao =~operador em [[ ... ]]:

#! /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
fonte
2
Uau, nunca soube Bash poderia fazer algo assim :)
Erathiel
FYI 1: ao escrever o regexp diretamente, não o coloque entre aspas . Por exemplo, [[ 'Example 123' =~ '([0-9]+)' ]]é falso, mas [[ 'Example 123' =~ ([0-9]+) ]]funciona como pretendido.
Jonathan H
FYI 2: a captura não funciona várias vezes. Por exemplo, [[ '1_2_3' =~ ([0-9]) ]] && echo ${BASH_REMATCH[@]}apenas corresponde 1.
Jonathan H
2

Usando o 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
fonte
2

Se isso é resultado de um programa / script que você escreveu e o texto é de fórmula (ou seja, segue exatamente esse padrão), você pode simplesmente usar 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
fonte
1

Se a linha sempre tiver exatamente essa estrutura, readpoderá fazer isso em uma única linha sem processos externos:

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

(também usando um herestring ). Isso salvará todas as palavras com as quais você não se importa x(a serem ignoradas) e os valores desejados nas respectivas variáveis.

Michael Homer
fonte