Trích xuất một chuỗi, theo một mẫu, trong một tập lệnh bash


17

Trong bash, giả sử rằng tôi có một chuỗi strname:

strname="ph7go04325r"

Tôi muốn trích xuất các ký tự giữa ký tự đầu tiên "3" và ký tự cuối cùng , lưu kết quả trong một chuỗi . Trong ví dụ trên, kết quả sẽ là:"r"strnamestrresultstrresult

strresult="25"

"3"tự đầu tiên không nhất thiết phải ở vị trí chuỗi 8 in strname; tương tự như vậy, cuối cùng "r"không nhất thiết phải ở vị trí chuỗi 11. Như vậy, cả hai chuỗi kí tự sau strnamenên mang lại strresult="25":

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

Ngoài ra, strname=ph12go04330raa"nên năng suất strresult="30".

Tôi chưa quen với bash scripting và tôi không biết bắt đầu thực hiện khớp mẫu chuỗi như thế này ở đâu. Bạn có đề nghị nào không?

Câu trả lời:


28

Bạn có thể sử dụng regex trong bash (3.0 trở lên) để thực hiện điều này:

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

Trong bash, các nhóm bắt giữ từ một regex được đặt trong mảng đặc biệt BASH_REMATCH. Phần tử 0 chứa toàn bộ trận đấu và 1 chứa kết quả khớp cho nhóm chụp đầu tiên.


10

Theo shcú pháp tiêu chuẩn (vì vậy sẽ hoạt động với mọi phiên bản bashhoặc bất kỳ trình bao tuân thủ POSIX nào khác), bạn sẽ làm:

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

Xem thêm exprgiải pháp cũ thậm chí sẽ hoạt động trên Unices 35 tuổi:

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

đứa với exprlà nếu trận đấu thất bại bạn sẽ có được một trạng thái thoát khác không (tốt), nhưng bạn cũng có được một trạng thái thoát khác không nếu giải quyết chuỗi trở về 0 (giống như với strname=zz300rzz).


Tôi nghĩ rằng phrasing của bạn không chính xác ngụ ý rằng điều này chỉ có thể được thực hiện với các phiên bản cũ hơn của bash. Tất nhiên, việc mở rộng tham số vẫn là một cách tiếp cận tốt trong hệ vỏ hiện đại.
kojiro

1
@kojiro, tôi hiểu ý của bạn. Công thức ban đầu là theo dõi câu trả lời của Jordan. Tôi đã cập nhật câu trả lời của mình.
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.