¿Cómo extraigo partes de una cadena a variables?

8

Tengo una línea de algún archivo como este:

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

Quiero extraer el 512^3, 16^3, 32^3y 800cuatro números de ello y asignarlos respectivamente a cuatro variables level, grid, boxesy taskspara otros usos.

¿Cómo puedo hacer esto?

Yulong Ao
fuente
Sí, los tres primeros tienen el formato a ^ by el último número habitual.
Yulong Ao

Respuestas:

15

Bash puede hacer coincidir expresiones regulares con el =~operador en [[ ... ]]:

#! /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
fuente
2
Wow, nunca supe que Bash podría hacer algo como esto :)
Erathiel
FYI 1: al escribir la expresión regular directamente, no lo ponga entre comillas . Por ejemplo, [[ 'Example 123' =~ '([0-9]+)' ]]es falso, pero [[ 'Example 123' =~ ([0-9]+) ]]funciona según lo previsto.
Jonathan H
FYI 2: la captura no funciona varias veces. Por ejemplo [[ '1_2_3' =~ ([0-9]) ]] && echo ${BASH_REMATCH[@]}solo coincide 1.
Jonathan H
2

Usando 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
fuente
2

Si esto es resultado de un programa / script que ha escrito y el texto es formulado (es decir, sigue este patrón exactamente), puede usarlo 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
fuente
1

Si la línea siempre tiene exactamente esta estructura, readpuede hacer esto en una sola línea sin procesos externos:

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

(también usando una herejía ). Esto guardará todas las palabras que no le interesan x(para ser ignoradas) y los valores que desea en sus respectivas variables.

Michael Homer
fuente