Bagaimana cara mengekstrak bagian string ke variabel?

8

Saya memiliki baris dari beberapa file seperti ini:

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

Saya ingin mengekstrak 512^3, 16^3, 32^3dan 800empat angka dari itu dan menetapkan mereka masing-masing untuk empat variabel level, grid, boxesdan tasksuntuk penggunaan lainnya.

Bagaimana saya bisa melakukan ini?

Yulong Ao
sumber
Ya, mereka bertiga pertama memiliki format a ^ b dan terakhir hanya nomor biasa.
Yulong Ao

Jawaban:

15

Bash dapat mencocokkan ekspresi reguler dengan =~operator di [[ ... ]]:

#! /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
sumber
2
Wow, tidak pernah tahu Bash bisa melakukan hal seperti ini :)
Erathiel
FYI 1: saat menulis regexp secara langsung, jangan menuliskannya dalam tanda kutip . Misalnya [[ 'Example 123' =~ '([0-9]+)' ]]salah, tetapi [[ 'Example 123' =~ ([0-9]+) ]]berfungsi seperti yang dimaksudkan.
Jonathan H
FYI 2: menangkap tidak berfungsi beberapa kali. Misalnya [[ '1_2_3' =~ ([0-9]) ]] && echo ${BASH_REMATCH[@]}hanya cocok 1.
Jonathan H
2

Menggunakan 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
sumber
2

Jika ini adalah output dari program / skrip yang Anda tulis dan teksnya adalah rumus (yaitu mengikuti pola ini persis) Anda bisa menggunakan 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
sumber
1

Jika garis selalu memiliki struktur ini, readdapat melakukan ini dalam satu baris tanpa proses eksternal:

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

(juga menggunakan herestring ). Ini akan menyimpan semua kata yang tidak Anda pedulikan x(untuk diabaikan) dan nilai yang Anda inginkan ke dalam variabel masing-masing.

Michael Homer
sumber