Kiểm tra shell để tìm một mẫu trong chuỗi


8

Tôi chỉ muốn hỏi liệu có bất kỳ lệnh nào sẽ hoạt động trên các shell thông thường (bash, dash, kornshell) không? Cần kiểm tra xem linebiến có chứa bất kỳ phần nào của đường dẫn không.

if [[ $line =~ "$PWD"$ ]] ;then

Bạn đã thử điều này? Lệnh đó sẽ hoạt động trong shell bash hiện đại giống như cách bạn gõ nó.
terdon

Điều đó sẽ không làm việc trong dấu gạch ngang.
Jonathan Leffler

Câu trả lời:


4

Có, các phiên bản gần đây của bash có thể làm điều này:

$ pwd
/home/terdon
$ line="I'm in /home/terdon"
$ [[ "$line" =~ "$PWD"$ ]] && echo yes
yes

Cú pháp tương tự hoạt động trong zsh và ksh nhưng không phải trong dấu gạch ngang. Theo tôi biết, dash không có khả năng như vậy.

Lưu ý rằng regex của bạn đang kiểm tra xem biến $line kết thúc bằng $PWD. Để kiểm tra xem có $PWDkhớp ở bất cứ đâu trong không $line, hãy xóa $:

$ line="I'm in /home/terdon, are you?"
$ [[ "$line" =~ "$PWD" ]] && echo yes
yes

1
Không, những thứ chỉ hoạt động trong bash-3.2 trở lên với điều kiện tùy chọn compat31 chưa được bật hoặc ksh93. Nó sẽ không hoạt động đúng trong các phiên bản bash hoặc zsh khác nếu $ PWD chứa các toán tử biểu thức chính quy.
Stéphane Chazelas

@ StéphaneChazelas có, đó là lý do tại sao tôi đã chỉ định rằng các phiên bản gần đây của bash có thể làm điều này. Đối với phần còn lại, tôi chỉ thử nó /home/terdon/foovới zsh, kshbash(4.3.25) và nó hoạt động tốt với tất cả chúng. Nó thực sự phá vỡ khi PWDchứa các toán tử regex. Điều đó chỉ đơn giản là không bao giờ xảy ra với tôi, cảm ơn!
terdon

14

Trong mọi vỏ tương thích POSIX, bạn có thể làm:

case $line in (*"$PWD"*)
#    whatever your then block had
;;esac

Điều này hoạt động trong bash, dashvà chỉ về bất kỳ shell nào khác mà bạn có thể đặt tên.

Nó cũng có thể được sử dụng để xử lý nhiều khả năng dễ dàng. Ví dụ:

case $line in 
(*"$PWD"*)
    echo \$PWD match\!
;;
(*"$OLDPWD"*)
    echo \$OLDPWD match\!
;;
(*)
    ! echo no match\!
;;esac

Bạn cũng có thể sử dụng luân phiên:

case $line in (*"$PWD"*|*"$OLDPWD"*)
    echo '$OLDPWD|$PWD match!'
;;esac

Lưu ý việc sử dụng trích dẫn ở trên:

  1. case $line ...
    • Đối tượng của một casecâu lệnh sẽ không được phân chia trên một trong hai $IFShoặc được sử dụng làm mẫu cho gen tên tệp. Điều này tương tự như cách đối số bên trái trong một [[bài kiểm tra được xử lý.
  2. (*"$PWD"*)
    • Ở đây, một bản mở rộng shell không phải chịu một trong hai $IFShoặc tạo tên tệp - một bản mở rộng không được trích dẫn sẽ không phân chia cũng như toàn cầu.
    • Nhưng một bản mở rộng không được trích dẫn ở đây có thể được hiểu là một mẫu chứ không phải là một chuỗi theo nghĩa đen, và do đó, một bản mở rộng có thể có nhiều ý nghĩa tùy thuộc vào việc nó có được trích dẫn hay không.
    • Điều quan trọng là trích dẫn bất kỳ biến nào được sử dụng trong một mẫu nên được hiểu theo nghĩa đen, giống như cách bạn trích dẫn các ký tự mẫu mà bạn muốn diễn giải theo nghĩa đen.
    • Ví dụ, nếu $PWDchứa a *và không được trích dẫn, nó sẽ được hiểu là một đối tượng mẫu và không phải là một nghĩa đen *được tìm kiếm.

@terdon - bạn đã đúng - các :bình luận đã gây nhầm lẫn, nhưng tôi sử dụng nó bởi vì nó không gen lỗi cú pháp hoặc vô tình chạy một số proggie tên bất cứ điều gì trong $PATH. Cách này vẫn sẽ gây ra lỗi cú pháp, nhưng ít nhất thì rõ ràng là nó nên.
mikeerv

2
Lưu ý rằng nếu bạn cần tính di động với vỏ Bourne (ví dụ đối với một số hệ thống cổ đại), bạn cần bỏ (:case $line in *"$PWD"*)
Stéphane Chazelas

@ StéphaneChazelas - đúng, nhưng nếu bạn làm điều đó, hãy zshbóp nghẹt nó.
mikeerv 30/03/2015

1
Ý anh là gì? Bạn đang đề cập đến những thứ như thế $(case a in a);; esac)nào?
Stéphane Chazelas

@ StéphaneChazelas - Tôi không thể sao chép nó, trừ khi tôi thực hiện lệnh phụ như trong ví dụ của bạn. Nó cũng kỳ lạ - zsh -cx '(case $1 in $2*) echo ok;;esac)' -- one ohoạt động, nhưng tiền tố : $phá vỡ nó. Tôi đoán đó là vấn đề tôi gặp phải trong quá khứ - nó luôn luôn không rõ ràng và tôi không bao giờ nhìn nó quá khó vì thêm phần ngoài cùng bên trái (luôn cố định nó. Cuối cùng, tôi chỉ viết nó ra như một zshđiều kỳ lạ và biến nó thành một quy tắc để sử dụng cả hai đầu.
mikeerv 30/03/2015
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.