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?

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.


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).


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.