Bash kiểm tra: những gì làm =


40
#!/bin/bash
INT=-5

if [[ "$INT" =~ ^-?[0-9]+$ ]]; then

echo "INT is an integer."

else

echo "INT is not an integer." >&2

exit 1

fi

Những gì hàng đầu ~làm trong biểu thức thường xuyên bắt đầu?


3
Đây không phải là regex, đây là mẫu thử nghiệm để xác định trận đấu regex ...
jasonwryan

5
Bạn đã đọc hướng dẫn bash? Bạn thấy gì không rõ ràng?
icarus

3
Tìm kiếm trang bash man cho = ~
Jeff Schaller

Câu trả lời:


46

Đây ~thực sự là một phần của toán tử =~thực hiện khớp biểu thức chính quy của chuỗi bên trái với biểu thức chính quy mở rộng ở bên phải.

[[ "string" =~ pattern ]]

Lưu ý rằng chuỗi nên được trích dẫn và biểu thức chính quy không nên được trích dẫn.

Một toán tử tương tự được sử dụng trong ngôn ngữ lập trình Perl.

Các biểu thức chính quy được hiểu bashgiống như các biểu thức mà GNU grephiểu với -Ecờ, tức là tập hợp các biểu thức chính quy mở rộng.


Hơi lạc đề, nhưng nên biết:

Khi khớp với biểu thức chính quy có chứa các nhóm bắt giữ, một phần của chuỗi được bắt bởi mỗi nhóm có sẵn trong BASH_REMATCHmảng. Các 0 / nhập đầu tiên trong mảng này tương ứng với &trong mô hình thay thế sedcủa lệnh thay thế (hoặc $&trong Perl), đó là các bit của chuỗi phù hợp với mô hình, trong khi các mục ở chỉ số 1 và trở đi tương ứng với \1, \2, vv . trong một sedmẫu thay thế (hoặc $1, $2v.v. trong Perl), tức là các bit khớp với từng dấu ngoặc đơn.

Thí dụ:

string=$( date +%T )

if [[ "$string" =~ ^([0-9][0-9]):([0-9][0-9]):([0-9][0-9])$ ]]; then
  printf 'Got %s, %s and %s\n' \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
fi

Điều này có thể đầu ra

Got 09, 19 and 14

nếu thời điểm hiện tại xảy ra là 09:19:14.

Các REMATCHbit của BASH_REMATCHtên mảng xuất phát từ "Regular Expression trận đấu", tức là "RE-Match".


Trong các bashshell không giống Bourne, người ta cũng có thể sử dụng exprcho kết hợp biểu thức chính quy giới hạn (chỉ sử dụng các biểu thức chính quy cơ bản).

Một ví dụ nhỏ:

$ string="hello 123 world"
$ expr "$string" : ".*[^0-9]\([0-9][0-9]*\)"
123

2
Nó giống như những gì grep -Echỉ hiểu trên các hệ thống GNU và chỉ khi sử dụng một biến không được trích dẫn làm mẫu [[ $var = $pattern ]](xem [[ 'a b' =~ a\sb ]]so với p='a\sb'; [[ 'a b' =~ $p ]]). Ngoài ra, hãy cẩn thận khi trích dẫn shell ảnh hưởng đến ý nghĩa của các toán tử RE và một số ký tự cần được trích dẫn cho mã thông báo shell có thể ảnh hưởng đến quá trình xử lý RE. [[ '\' =~ [\/] ]]trả về sai. ksh93thậm chí còn có vấn đề tồi tệ hơn Xem zsh(hoặc bash 3.1) để biết cách tiếp cận saner trong đó trích dẫn shell và RE được phân tách rõ ràng. Nội dung [của zshyashcũng có một =~toán tử.
Stéphane Chazelas

2
rất mát mẻ off-topic! +1 (
JJoao

@ StéphaneChazelas Làm thế nào "saner" rằng cả hai trận đấu này trong zsh?: [[ "This is a fine mess." =~ T.........fin*es* ]]; [[ "This is a fine mess." =~ T.........fin\*es\* ]]. Hoặc là một trích dẫn *cũng phù hợp? [[ "This is a fine mess." =~ "T.........fin*es*" ]].
sorontar

Đó là saner (IMO) trong đó quy tắc đơn giản hơn nhiều. Shell trích dẫn và RE thoát là rõ ràng riêng biệt. Trong [[ a =~ .* ]]hoặc [[ a =~ '.*' ]]hoặc [[ a =~ \.\* ]], cùng một .*RE được truyền cho =~toán tử. OTH, trong bash, [[ '\' =~ [)] ]]trả về một lỗi, bạn có biết mà không thử xem nó có [[ '\' =~ [\)] ]]khớp không? Làm thế nào về [[ '\' =~ [\/] ]](nó làm trong ksh93). Làm thế nào về c='a-z'; [[ a =~ ["$c"] ]](so sánh với các =nhà điều hành)? Xem thêm: [[ '\' =~ [^]"."] ]]đó trả về false ... Lưu ý rằng bạn có thể làm shopt -s compat31trong bashđể có được zshhành vi.
Stéphane Chazelas

zshbash -o compat31Hành vi của / [[ a =~ '.*' ]]cũng phù hợp với [ a '=~' '.*' ](đối với [việc triển khai hỗ trợ =~) hoặc expr a : '.*'. OTOH, nó không phù hợp với [[ a = '*' ]]vs [[ a = * ]](nhưng sau đó, các khối là một phần của ngôn ngữ shell, trong khi RE thì không).
Stéphane Chazelas

4

Bạn nên đọc các trang bash man, dưới [[ expression ]]phần.

An additional binary operator, =~, is available, with the same precedence as == and !=. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex(3)).

Câu chuyện dài, =~là một nhà điều hành, giống như ==!=. Nó không có gì để làm với regex thực tế trong chuỗi bên phải của nó.


Bạn có thể tìm ra một số ví dụ minh họa việc sử dụng =~trong cuộc sống thực ...?
George Vasiliou

1
@GeorgeVasiliou Tôi sử dụng nó khá thường xuyên trong các tập lệnh đưa đầu ra từ một lệnh thành một biến. Sau đó, biến được kiểm tra để xem nếu nó phù hợp với một số mẫu chuỗi. Điều này hữu ích ví dụ nếu bạn muốn thực hiện một số hành động dựa trên một số đầu ra lỗi từ lệnh đó.
Michael Martinez

@Sokel Đối với một số người, thì RT RTMM nói dễ hơn làm. ⋯ man [[ expresssion ]]man [[lợi nhuận gì cả. help [[trả về thông tin hữu ích, kể từ [[lệnh bash nội bộ, nhưng không cho biết =~sử dụng cú pháp regex cơ bản hay mở rộng. Văn bản bạn trích dẫn là từ trang bash man. Tôi nhận ra bạn đã nói rằng người đọc các trang bash man, nhưng lúc đầu, tôi nghĩ bạn có nghĩa là đọc các trang của người đàn ông trong bash. Ở bất kỳ giá nào, man bashtrả về một tệp khổng lồ, dài 4139 dòng (72 trang). Nó có thể được tìm kiếm bằng cách nhấn /▒▒▒, trong đó có một biểu thức chính quy, hương vị mà tinh thần giống =~nhưisis không được chỉ định.
Alex Quinn
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.