Mengekstraksi string, sesuai dengan pola, dalam skrip bash

17

Dalam bash, anggaplah saya memiliki string strname:

strname="ph7go04325r"

Saya ingin mengekstraksi karakter antara karakter pertama "3" dan karakter terakhir , menyimpan hasilnya dalam sebuah string . Pada contoh di atas, hasilnya adalah:"r"strnamestrresultstrresult

strresult="25"

"3"Karakter pertama tidak harus pada posisi string 8 in strname; juga, lalu "r"ini tidak selalu pada posisi tali 11. Dengan demikian, kedua string berikut strnameharus menghasilkan strresult="25":

strname="ph11go04325raa"
strname="325r"
strname="rgo04325raa"

Juga, strname=ph12go04330raa"harus menghasilkan strresult="30".

Saya baru mengenal bash scripting, dan saya tidak tahu harus mulai dari mana dari pencocokan pola string seperti ini. Apakah Anda punya saran?

Andrew
sumber

Jawaban:

28

Anda bisa menggunakan regex di bash (3.0 atau lebih tinggi) untuk mencapai ini:

if [[ $strname =~ 3(.+)r ]]; then
    strresult=${BASH_REMATCH[1]}
else
    echo "unable to parse string $strname"
fi

Di bash, grup tangkap dari regex ditempatkan di larik khusus BASH_REMATCH. Elemen 0 berisi seluruh pertandingan, dan 1 berisi pertandingan untuk grup tangkapan pertama.

jordanm
sumber
10

Dalam shsintaks standar (sehingga akan bekerja dengan versi bashapa pun atau shell yang sesuai dengan POSIX lainnya), Anda akan melakukannya:

case $strname in
  (*3*r*) 
    strresult=${strname#*3}
    strresult=${strresult%r*};;
  (*)
    printf >&2 '%s\n' "Unable to parse string $strname"
esac

Lihat juga exprsolusi lama yang bahkan akan berfungsi pada Unix berusia 35 tahun:

expr "x$strname" : 'x[^3]*3\(.*\)r'

Kekhasan lama dengan expradalah bahwa jika pertandingan gagal Anda mendapatkan status keluar non-nol (baik), tetapi Anda juga mendapatkan status keluar non-nol jika string dikembalikan ke 0 (seperti dengan strname=zz300rzz).

Stéphane Chazelas
sumber
Saya pikir frasa Anda salah mengimplikasikan bahwa ini hanya dapat dilakukan dengan versi bash yang lebih lama. Ekspansi parameter, tentu saja, masih merupakan pendekatan yang bagus di shell modern.
kojiro
1
@ Kojiro, saya mengerti maksud Anda. Formulasi awal adalah untuk menindaklanjuti jawaban Jordan. Saya telah memperbarui jawaban saya.
Stéphane Chazelas