Cách tốt hơn để làm tiếng vang $ x | tiếng vang trầm lắng và tiếng vang $ x | grep


14

Tôi thường tìm thấy điều này trong các kịch bản (và, tôi phải thừa nhận, tự viết nó):

a=$(echo "$x" | sed "s/foo/bar/")

hoặc là

if echo "$x" | grep -q foo
then
    ...
fi

Xem xét "foo" để bao gồm một số công cụ regex.

Tôi cảm thấy rằng nên có - và rất có thể - một cách tốt hơn để diễn đạt điều này, một cách không liên quan đến hai lệnh và một đường ống nhưng kết hợp điều đó thành một biểu thức nhỏ gọn hơn.

Tôi không thể tìm thấy nó. Có ai không


tôi hy vọng biểu thức này được sử dụng thường xuyên do sự kết hợp của sự thiếu hiểu biết (không biết các lựa chọn thay thế) và khả năng duy trì (biết các lựa chọn thay thế nhưng chọn cách này là đơn giản hơn để hiểu). tôi có thể nói nhanh những ví dụ của bạn làm gì, nhưng tôi cần một tài liệu tham khảo vỏ để tìm ra các phương án trong câu trả lời của grawity và Dan McG.
quack quixote

3
Nhân tiện, phương pháp ưa thích để thực hiện thay thế lệnh là $()thay vì backticks.
Tạm dừng cho đến khi có thông báo mới.

2
Nó cũng là một ý tưởng tốt để trích dẫn mở rộng để khoảng trắng được bảo vệ: a="$(echo "$x" | sed "s/foo/bar/")"if echo "$x" | grep foo; ….
Chris Johnsen

Nhận xét tốt về $ () so với ``. Tôi thấy kỹ năng bash của tôi chưa tuyệt lắm.
DevSolar

Câu trả lời:


12

Trừ khi bạn giả định một lớp vỏ cụ thể, không có cách nào tốt hơn để thực hiện điều này ngoài tiếng vang của đường ống đến công cụ đá (hoặc chỉ là một công cụ của chính bản thân như expr ); đó là tất cả những gì bạn thực sự có thể tin tưởng với vỏ Bourne truyền thống và / hoặc vỏ POSIX . Nếu bạn xem xét các shell khác, thì có một số khả năng tích hợp khác.

ksh

  • mẫu thêm: ?(pattern-list), *(pattern-list), {n}(pattern-list), {n,m}(pattern-list), @(pattern-list), !(pattern-list);
  • bộ xác định %P printf để chuyển đổi một biểu thức chính quy mở rộng thành một mẫu (và %Rcho biểu thức chính quy mở rộng thành mẫu);
  • các expr == patternđiều kiện trong [[ expr ]]các bài kiểm tra;
  • việc ${param/pattern/replacement}mở rộng tham số.

bash

  • các extglobtùy chọn để cho phép hầu hết các mẫu thêm ksh (không {n}{n,m});
  • các expr == patternđiều kiện (trong [[ expr ]]các bài kiểm tra);
  • việc ${param/pattern/replacement}mở rộng tham số;
  • (trong các phiên bản mới hơn) expr =~ extregexpđiều kiện (trong [[ expr ]]các thử nghiệm) có thể phù hợp với các biểu thức chính quy mở rộng
    • với các biểu thức con được ngoặc đơn và BASH_REMATCHtham số, việc thay thế kiểu sed có thể được thực hiện.

zsh

  • các mẫu mở rộng của riêng nó với EXTENDED_GLOBtùy chọn;
  • mô hình mở rộng giống như ksh với KSH_GLOBtùy chọn;
  • các expr == patternđiều kiện (trong [[ expr ]]các bài kiểm tra);
  • việc ${pattern/pattern/replacement}mở rộng tham số;
  • các expr =~ extregexpđiều kiện (trong [[ expr ]]các bài kiểm tra) có thể phù hợp với biểu thức thông thường kéo dài,
    • nó có thể sử dụng PCRE thay vì các biểu thức chính quy mở rộng đơn giản nếu tùy chọn RE_MATCH_PCRE được đặt,
    • với các biểu thức con được ngoặc đơn, MATCHtham số và matchtham số (hoặc BASH_REMATCHvới tập BASH_REMATCHtùy chọn), có thể thực hiện thay thế kiểu sed ;
  • các zsh/pcremô-đun cung cấp pcre_compile, pcre_studypcre_matchcác lệnh và -pcre-match kiểm tra điều kiện (trong [[ expr ]]các bài kiểm tra);
  • các zsh/regexmô-đun cung cấp các -regex-match bài kiểm tra điều kiện (trong [[ expr ]]các bài kiểm tra).

Ồ Hoàn thành như người ta có thể mong muốn. Chắc chắn là một người chiến thắng.
DevSolar

6

Để thay thế dòng sed, hãy làm một cái gì đó như

${a/foo/bar} hoặc là ${a//foo/bar}

Trong hình thức đầu tiên, chỉ có trường hợp đầu tiên được thay thế. Hình thức thứ hai là tìm kiếm toàn cầu & thay thế.

Trong trường hợp của bạn, nó sẽ là

Thay vì:

if echo $x | grep foo
then
    ...
fi

Cân nhắc sử dụng:

if [ $x =~ foo ]
then
    ...
fi

Đâu foolà một biểu thức chính quy.


Trong đó vỏ nào hoạt động?
Peltier

1
if [ $x =~ foo ]đưa ra một thông báo lỗi ở đây. if [[ $x =~ foo ]]Tuy nhiên, hoạt động tuyệt vời. Cảm ơn!
DevSolar

1
Tất cả những điều này là bashism, họ yêu cầu bash. Ngoài ra, =~yêu cầu bash> = 3 iirc.
ℝaphink

1
Iirc cũng vậy, foo không phải là một biểu thức thông thường (như trong PCRE) trong các ví dụ này, nhưng sử dụng các ký tự đại diện. Có nhiều tính tốt hơn của bash trong trang bash, phần "Mở rộng tham số". Tôi đặc biệt đánh giá cao những thứ như ${a##foo}${a%%bar}.
ℝaphink

3
Toán tử khớp =~sử dụng các biểu thức chính quy. Điều này đúng, ví dụ: [[ "abcdddde" =~ ^a.*d+.g* ]]( chẳng hạn như bằng 0 hoặc nhiều g hơn là g-wildcard chẳng hạn).
Tạm dừng cho đến khi có thông báo mới.

2

Một cách tương thích posix tốt để kiểm tra nếu một biến chứa mẫu là:

test ${var##*foo*} || <do something>;

Cú pháp mở rộng tham số là:

 ${parameter##pattern}

nơi patternlà một mẫu vỏ .

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.