Wie extrahiere ich Teile eines Strings in Variablen?

8

Ich habe eine Zeile aus einer Datei wie dieser:

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

Ich möchte , dass die extrahieren 512^3, 16^3, 32^3und 800vier Zahlen von ihr und ordnen sie jeweils zu vier Variablen level, grid, boxesund tasksfür andere Zwecke.

Wie kann ich das machen?

Yulong Ao
quelle
Ja, die ersten drei haben das Format a ^ b und die letzte nur übliche Nummer.
Yulong Ao

Antworten:

15

Bash kann reguläre Ausdrücke mit dem =~Operator abgleichen in [[ ... ]]:

#! /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
quelle
2
Wow, ich wusste nie, dass Bash so etwas tun kann :)
Erathiel
Zu Ihrer Information 1: Wenn Sie den regulären Ausdruck direkt schreiben, setzen Sie ihn nicht in Anführungszeichen . Zum Beispiel [[ 'Example 123' =~ '([0-9]+)' ]]ist falsch, [[ 'Example 123' =~ ([0-9]+) ]]funktioniert aber wie beabsichtigt.
Jonathan H
Zu Ihrer Information 2: Die Erfassung funktioniert nicht mehrmals. Zum Beispiel [[ '1_2_3' =~ ([0-9]) ]] && echo ${BASH_REMATCH[@]}nur Übereinstimmungen 1.
Jonathan H
2

Mit 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
quelle
2

Wenn dies von einem Programm / Skript ausgegeben wird, das Sie geschrieben haben, und der Text formelhaft ist (dh genau diesem Muster folgt), können Sie ihn einfach verwenden 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
quelle
1

Wenn die Zeile immer genau diese Struktur hat, readkönnen Sie dies in einer einzelnen Zeile ohne externe Prozesse tun:

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

(auch mit einem Herestring ). Dadurch werden alle Wörter, die Sie nicht interessieren x(zu ignorieren), und die gewünschten Werte in den jeweiligen Variablen gespeichert.

Michael Homer
quelle