Tại sao dấu [az] khớp với số?


13

Tôi có 3 thư mục tại đường dẫn hiện tại.

$ls
a_0db_data  a_clean_0db_data  a_clean_data
$ls a_*_data
a_0db_data:

a_clean_0db_data:

a_clean_data:

$ls a_[a-z]*_data
a_clean_0db_data:

a_clean_data:

Tôi dự kiến ​​lệnh ls cuối cùng chỉ phù hợp a_clean_data. Tại sao nó cũng phù hợp với cái có chứa 0?

bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)

2
Xem câu hỏi này để biết thêm về sự khác biệt giữa biểu thức chính quy và hình cầu.
terdon

4
Vì vậy, thực tế phù a_*_datahợp với bất kỳ tập tin này không làm bạn ngạc nhiên?
Cthulhu

@Cthulhu bạn hiểu ý tôi rồi!
dùng13107

Câu trả lời:


29

Phần [a-z]không phải là những gì phù hợp với số lượng; đó là *. Bạn có thể gây nhầm lẫn vỏ globbingbiểu thức thông thường .

Các công cụ như grepchấp nhận các hương vị khác nhau của regexes ( cơ bản theo mặc định, -Eđể mở rộng, -Pcho Perl regex )

Ví dụ: ( -vđảo ngược trận đấu)

$ ls a_[a-z]*_data | grep -v "[0-9]"
a_clean_data

Nếu bạn muốn sử dụng regex bash, đây là một ví dụ về cách kiểm tra xem biến $refcó phải là số nguyên không:

re='^[0-9]+$'
if ! [[ $ref =~ $re ]] ; then
  echo "error"
fi

Làm thế nào để sử dụng bash regex sau đó? (xem tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_01.html )
dùng13107


21

Vì vậy, vấn đề là: tại sao không a_[a-z]*_datakhớp a_clean_0db_data?

Điều này có thể được chia thành bốn phần:

  • a_phù hợp với sự khởi đầu a_clean_0db_data, để lại clean_0db_datacho phù hợp

  • [a-z]phù hợp với bất kỳ nhân vật nào trong phạm vi a-z(ví dụ c), lean_0db_datađể phù hợp

  • * phù hợp với bất kỳ số lượng ký tự, ví dụ lean_0db

  • _data phù hợp với dấu _data

Trong các biểu thức chính quy, [a-z]*sẽ có nghĩa là bất kỳ số lượng ký tự nào (bao gồm 0) trong phạm vi a..z , nhưng bạn đang xử lý toàn cầu shell chứ không phải với các biểu thức thông thường.

Nếu bạn muốn biểu thức chính quy, một vài findtriển khai có một -regexvị ngữ cho điều đó:

find . -maxdepth 1 -regex "^.*/a_[a-z]*_data$"

Các -maxdepthchỉ ở đây để hạn chế kết quả tìm kiếm vào thư mục bạn đang ở. Các biểu thức chính quy phù hợp với toàn bộ tên tập tin, do đó tôi đã thêm một ^.*/để phù hợp với đường dẫn phần


11

*trong các mẫu vỏ khớp với 0 hoặc nhiều ký tự. Không nên nhầm lẫn với *toán tử biểu thức chính quy có nghĩa là 0 hoặc nhiều hơn các nguyên tử trước .

Không có tương đương với biểu thức chính quy *trong các mẫu vỏ cơ bản. Tuy nhiên, các shell khác nhau có phần mở rộng cho điều đó.

  • ksh*(something):

    ls a_*([a-z])_data
  • bạn có thể có giống nhau ở bashvới shopt -s extglobhoặc zshvới setopt kshglob:

    shopt -s extglob
    ls a_*([a-z])_data
  • Trong zshkhi extendedglobkích hoạt, #tương đương với regrec *:

    setopt extendedglob
    ls a_[a-z]#_data
  • Trong các phiên bản gần đây của ksh93, bạn cũng có thể sử dụng các biểu thức thông thường trong các khối. Ở đây với các biểu thức chính quy mở rộng :

    ls ~(E:a_[a-z]*_data)

Lưu ý rằng [a-z]phù hợp với những thứ khác nhau tùy thuộc vào ngôn ngữ hiện tại. Nó thường chỉ phù hợp với các chữ cái không có dấu 26 ađến zLatin trong Cmiền địa phương. Ở các địa phương khác, nó thường phù hợp hơn và không phải lúc nào cũng có ý nghĩa. Để phù hợp với một chữ cái trong miền địa phương của bạn, bạn có thể thích [[:alpha:]].


Bạn có thể đưa ra một ví dụ về [a-z]khớp nhiều hơn mà 26 chữ cái khớp với ngôn ngữ C không? Điều tôi nhớ từ lần cuối cùng nhìn vào điều này, tất cả các mã hóa được sử dụng thực tế trong các biến thể Unix đều có ISO-646 làm cơ sở (sau đó là 128 mã trên được sử dụng khác nhau, trực tiếp cho các ký tự trong mã hóa như ISO-8859-X, được kết hợp trong mã hóa như UTF-8 hoặc gia đình EUC). Ngay cả AIX cũng không có địa phương EBCDIC (ít nhất là có sẵn cho tôi). Tôi nhớ đã cố gắng tìm xem các tiêu chuẩn POSIX / UNIX có yêu cầu không, nhưng tôi không nhớ kết quả.
AProgrammer

1
@AProgrammer, độc lập với mã hóa, dựa trên thứ tự sắp xếp (LC_COLLATE). [a-z]thường bao gồm éhoặc í(nhưng không nhất thiết ź) ở các địa phương nơi bộ ký tự có chúng, cho dù mật mã trong mã hóa đó có nằm giữa a và z hay không. Chỉ miền địa phương C đảm bảo một thứ tự sắp xếp dựa trên giá trị điểm mã. Xem câu trả lời khác này để biết thêm chi tiết.
Stéphane Chazelas

Ok, điều tôi đã bỏ lỡ là phạm vi được diễn giải theo trình tự đối chiếu hiện tại.
AProgrammer
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.