Comment extraire des parties d'une chaîne en variables?


8

J'ai une ligne d'un fichier comme celui-ci:

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

Je veux extraire le 512^3, 16^3, 32^3et 800quatre numéros et de les attribuer respectivement à quatre variables level, grid, boxeset taskspour une autre utilisation.

Comment puis-je faire ceci?


Oui, les trois premiers ont le format a ^ b et le dernier juste un numéro habituel.
Yulong Ao

Réponses:


15

Bash peut faire correspondre des expressions régulières avec l' =~opérateur dans [[ ... ]]:

#! /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

2
Wow, je ne savais pas que Bash pouvait faire quelque chose comme ça :)
Erathiel

FYI 1: lors de l'écriture de l'expression rationnelle directement, ne le mettez pas entre guillemets . Par exemple, [[ 'Example 123' =~ '([0-9]+)' ]]est faux, mais [[ 'Example 123' =~ ([0-9]+) ]]fonctionne comme prévu.
Jonathan H

Pour info 2: la capture ne fonctionne pas plusieurs fois. Par exemple, [[ '1_2_3' =~ ([0-9]) ]] && echo ${BASH_REMATCH[@]}ne correspond qu'à 1.
Jonathan H

2

Utilisation de 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

2

Si cela provient d'un programme / script que vous avez écrit et que le texte est de formule (c'est-à-dire suit exactement ce modèle), vous pouvez simplement l'utiliser 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 -)

1

Si la ligne a toujours exactement cette structure, readpeut le faire sur une seule ligne sans processus externe:

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

(en utilisant également une herestring ). Cela sauvera tous les mots qui ne vous intéressent pas x(à ignorer) et les valeurs que vous vouliez dans leurs variables respectives.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.