8

I have a line from some file like this:

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

I want to extract the 512^3, 16^3, 32^3 and 800 four numbers from it and assign them respectively to four variables level, grid, boxes and tasks for other use.

How can I do this?

  • Yes, the first three of them has the format a^b and last one just usual number. – Yulong Ao Apr 16 '15 at 8:03
15

Bash can match regular expressions with the =~ operator 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
  • 2
    Wow, never knew Bash could do something like this :) – Erathiel Apr 16 '15 at 8:26
  • FYI 1: when writing the regexp directly, do not put it in quotes. For example [[ 'Example 123' =~ '([0-9]+)' ]] is false, but [[ 'Example 123' =~ ([0-9]+) ]] works as intended. – Jonathan H Sep 20 '18 at 16:36
  • FYI 2: capture does not work multiple times. For example [[ '1_2_3' =~ ([0-9]) ]] && echo ${BASH_REMATCH[@]} only matches 1. – Jonathan H Sep 20 '18 at 16:36
2

Using 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

If this is output from a program / script you've written and the text is formulaic (i.e. follows this pattern exactly) you can just use 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

If the line always has exactly this structure, read can do this in a single line with no external processes:

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

(also using a herestring). This will save all the words you don't care about into x (to be ignored) and the values you wanted into their respective variables.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.