Cách kiểm tra xem một chuỗi có chứa chuỗi con trong Bash hay không

How Check If String Contains Substring Bash



Câu hỏi đặt ra là làm thế nào để kiểm tra xem một chuỗi có chứa chuỗi con trong Bash hay không. Câu trả lời là: sử dụng Khớp mẫu. Điều này dẫn đến một câu hỏi khác, đó là: Khớp mẫu là gì? Vâng, một cụm từ trong một câu có những đặc điểm nhất định. Đó là lý do tại sao nó khác với các cụm từ khác trong cùng một câu hoặc trong các câu khác. Các đặc điểm có thể được mã hóa dưới dạng một mẫu. Bằng cách đó, một cụm từ cụ thể trong một chuỗi có thể được xác định. Bài viết này giải thích cách xác định một chuỗi con cụ thể trong một chuỗi lớn hơn, thay thế chuỗi con được so khớp bằng một chuỗi con khác và định vị bất kỳ chuỗi con nào trong một chuỗi lớn hơn theo chỉ mục. Tuy nhiên, trước khi đi sâu vào giải thích, người ta phải nhớ lại các cách khác nhau mà một chuỗi được thiết lập trong Bash.

String by Escaping Spaces

Một chuỗi có thể được xây dựng bằng cách thay thế từng khoảng trắng bằng chuỗi thoát khoảng trắng, ‘’; như trong:







myVar= Du lịch trong Ai Cập là một trong quốc gia 's dẫn đầu kinh tế các ngành công nghiệp.
quăng đi $ myVar

Đầu ra là:



Du lịch ở Ai Cập là một trong những ngành kinh tế hàng đầu của đất nước.



Lưu ý: dấu nháy đơn cũng sử dụng trình tự thoát khoảng trắng.





Chuỗi theo dấu ngoặc kép

Lập trình viên có thời gian để thoát khỏi tất cả các khoảng trắng trong một chuỗi không? Không. Do đó, sử dụng hai dấu nháy đơn để phân tách một chuỗi sẽ tốt hơn; nhu la:

myVar='Du lịch ở Ai Cập là một trong những đất nước' ''các ngành kinh tế hàng đầu.'

Một chuỗi được trích dẫn đơn không cho phép mở rộng (thay thế bằng hiệu ứng của nó) của bất kỳ chuỗi thoát nào. May mắn thay, nếu hai chuỗi được mã hóa bên cạnh nhau, chúng sẽ được coi là một chuỗi. Một chuỗi thoát có thể được chèn vào giữa, như đã thực hiện ở trên. Trình tự thoát sẽ được mở rộng. Vì vậy, đầu ra trở thành:



Du lịch ở Ai Cập là một trong những ngành kinh tế hàng đầu của đất nước.

Chuỗi theo dấu ngoặc kép

Với dấu ngoặc kép, trình tự thoát cũng không được mở rộng, nhưng các biến được mở rộng. Đoạn mã sau minh họa điều này:

myVar= Du lịch trong Ai Cập là một trong quốc gia 's dẫn đầu kinh tế các ngành công nghiệp.
quăng đi $ myVar

Đầu ra là:

Du lịch ở Ai Cập là một trong những ngành kinh tế hàng đầu của đất nước.

Lưu ý: dấu nháy đơn cũng sử dụng trình tự thoát khoảng trắng.

Trong bài viết này, loại chuỗi chính được xem xét là chuỗi trong dấu nháy đơn.

Các nguyên tắc cơ bản về biểu thức chính quy

Regex

Hãy xem xét chuỗi này:

Thế giới này không thực sự là nhà của chúng ta.

Hãy để thế giới là một chuỗi quan tâm. Khi đó, chuỗi lớn (toàn bộ chuỗi) được gọi là chuỗi đích hoặc đơn giản là đích. ‘World’ trong dấu ngoặc kép được gọi là biểu thức chính quy hoặc đơn giản hơn là regex. Trong trường hợp này, nội dung, thế giới, là khuôn mẫu.

Kết hợp đơn giản

Trong đoạn mã sau, nếu từ 'world' được tìm thấy trong mục tiêu, chúng tôi sẽ nói rằng từ này đã được đối sánh.

P='Thế giới này không thực sự là nhà của chúng ta.'
reg='thế giới'
nếu như [[ $ str= ~$ reg ]];sau đó
quăng đitìm
khác
quăng đikhông tìm thấy
thì là ở

= ~, là toán tử gán theo sau là ~, được gọi là toán tử ràng buộc. Điều kiện kiểm tra xem mẫu có được khớp trong chuỗi mục tiêu hay không. Nếu một chuỗi con tương ứng với mẫu được tìm thấy trong mục tiêu, câu lệnh echo sẽ hiển thị được tìm thấy. Nếu nó không được tìm thấy, thì câu lệnh echo sẽ không được tìm thấy. Đầu ra cho mã này là:

tìm

Như mô hình, thế giới, được tìm thấy trong mục tiêu. Lưu ý rằng khoảng cách phân định sau [[và trước]] đã được duy trì.

Mẫu

Trong đoạn mã trên, 'world' trong dấu ngoặc kép là regex trong khi bản thân world là mẫu. Đây là một mô hình đơn giản. Tuy nhiên, hầu hết các mẫu không đơn giản như vậy. Một mẫu là một đặc điểm của một chuỗi con được tìm thấy. Và do đó, mẫu Bash sử dụng một số siêu ký tự nhất định. Một siêu ký tự là một ký tự về các ký tự khác. Ví dụ: Bash Pattern sử dụng các siêu ký tự sau:

^ $ . * +? () [] {} |

Một biểu thức chính quy cũng có thể được nhập trong dấu ngoặc kép điều kiện. Nhưng nó không nhất thiết phải nằm trong dấu ngoặc kép. Vì vậy, trong trường hợp này, nó là một khuôn mẫu theo nghĩa đen.

Các lớp nhân vật

Dấu ngoặc vuông

Đầu ra của mã sau được tìm thấy, có nghĩa là một trận đấu đã diễn ra:

P='Con mèo đã vào trong buồng.'
nếu như [[ $ str= ~[cbr]tại]];sau đó
quăng đitìm
thì là ở

Mẫu [cbr] at đã khớp với con mèo, bắt đầu bằng ‘c’, tiếp tục và kết thúc bằng tại. [cbr] at có nghĩa là, khớp với ‘c’ hoặc ‘b’ hoặc ‘r’ theo sau là at.

Đầu ra của mã sau được tìm thấy, có nghĩa là một trận đấu đã diễn ra:

P='Con dơi đã vào trong buồng.'
nếu như [[ $ str= ~[cbr]tại]];sau đó
quăng đitìm
thì là ở

Mẫu, [cbr] at có dấu dơi phù hợp, bắt đầu bằng ‘b’, tiếp tục và kết thúc bằng tại. [cbr] at có nghĩa là, khớp với ‘c’ hoặc ‘b’ hoặc ‘r’ theo sau là at.

Đầu ra của mã sau được tìm thấy, có nghĩa là một trận đấu đã diễn ra:

P='Con chuột đã vào trong buồng.'
nếu như [[ $ str= ~[cbr]tại]];sau đó
quăng đitìm
thì là ở

Mẫu, [cbr] at có con chuột phù hợp, bắt đầu bằng ‘r’, tiếp tục và kết thúc bằng tại.

Trong các mẫu mã trên, lập trình viên không biết mèo hay dơi hay chuột tồn tại trong chuỗi đích. Tuy nhiên, anh ấy biết rằng chuỗi con bắt đầu bằng ‘c’ hoặc ‘b’ hoặc ‘r’, sau đó tiếp tục và kết thúc bằng at. Dấu ngoặc vuông trong một mẫu cho phép các ký tự có thể có khác nhau khớp với một ký tự tại một vị trí so với các ký tự khác trong mục tiêu. Vì vậy, dấu ngoặc vuông chứa một tập hợp các ký tự, trong đó một ký tự được so khớp với một chuỗi con. Cuối cùng, nó là chuỗi con hoàn chỉnh được so khớp.

Phạm vi ký tự

Trong đoạn mã trên [cbr] là một lớp. Ngay cả khi ‘c’ hoặc ‘b’ hoặc ‘r’ tương ứng với một ký tự duy nhất, nếu ngay sau đó không khớp, mẫu sẽ không khớp với bất kỳ ký tự nào.

Vâng, có một số phạm vi nhất định sẽ tạo thành một lớp. Ví dụ, từ 0 đến 9 chữ số tạo thành lớp, [0-9] với 0 và 9 được bao gồm. Chữ thường ‘a’ thành ‘z’ tạo thành lớp [a-z] với ‘a’ và ‘z’ được bao gồm. Chữ hoa ‘A’ đến ‘Z’ tạo thành lớp [A-Z] với ‘A’ và ‘Z’ được bao gồm. Từ một lớp, nó là một trong những ký tự sẽ khớp với một ký tự trong chuỗi.

Đoạn mã sau tạo ra một kết quả phù hợp:

nếu như [[ 'ID8id'= ~[0-9] ]];sau đó
quăng đitìm
thì là ở

Lần này đích là một chuỗi ký tự trong điều kiện. 8, là một trong những số có thể có trong phạm vi, [0-9], đã khớp với 8 trong chuỗi, ‘ID8id’. Đoạn mã trên tương đương với:

nếu như [[ 'ID8id'= ~[0123456789] ]];sau đó
quăng đitìm
thì là ở

Ở đây, tất cả các số có thể đã được viết theo mẫu, vì vậy không có gạch nối.

Trong đoạn mã sau, một kết quả phù hợp thu được:

nếu như [[ 'ID8iD'= ~[a-z] ]];sau đó
quăng đitìm
thì là ở

Đối sánh giữa chữ thường ‘i’ của dải ô, [a-z] và chữ thường ‘i’ của chuỗi mục tiêu, ‘ID8iD’.

Hãy nhớ rằng: phạm vi là một lớp. Lớp có thể là một phần của một mẫu lớn hơn. Vì vậy, trong một mẫu, văn bản có thể ở trước và / hoặc sau lớp. Đoạn mã sau minh họa điều này:

nếu như [[ 'ID8id là số nhận dạng'= ~ ID[0-9]Tôi ]];sau đó
quăng đitìm
thì là ở

Đầu ra là: tìm thấy. ‘ID8id’ từ mẫu đã khớp với ‘ID8id’ trong chuỗi mục tiêu.

Phủ định

Không lấy được đối sánh từ mã sau:

nếu như [[ '0123456789101112'= ~[^0-9] ]];sau đó
quăng đitìm
khác
quăng đikhông tìm thấy
thì là ở

Đầu ra là:

không tìm thấy

Nếu không có ^ phía trước phạm vi, trong dấu ngoặc vuông, số không của phạm vi sẽ khớp với số 0 đầu tiên của chuỗi mục tiêu. Vì vậy, ^ ở phía trước của một phạm vi (hoặc các ký tự tùy chọn) phủ định lớp.

Đoạn mã sau tạo ra kết quả khớp vì điều kiện đọc: khớp với bất kỳ ký tự không phải chữ số nào ở bất kỳ vị trí nào trong mục tiêu:

nếu như [[ 'ABCDEFGHIJ'= ~[^0-9] ]];sau đó
quăng đitìm
khác
quăng đikhông tìm thấy
thì là ở

Vì vậy, đầu ra là: tìm thấy.

[^ 0-9] có nghĩa là một chữ số không phải chữ số, vì vậy [^ 0-9] là phủ định của [0-9].

[^ a-z] có nghĩa là một chữ cái không phải chữ thường, vì vậy [^ a-z] là phủ định của [a-z].

[^ A-Z] có nghĩa là một chữ cái không viết hoa, vì vậy [^ A-Z] là phủ định của [A-Z].

Các phủ định khác có sẵn.

Dấu chấm (.) Trong Mẫu

Dấu chấm (.) Trong mẫu khớp với bất kỳ ký tự nào kể cả chính nó. Hãy xem xét đoạn mã sau:

nếu như [[ '6759WXY.A3'= ~ 7,9W.Y.A]];sau đó
quăng đitìm
thì là ở

Đầu ra của mã được tìm thấy vì các ký tự khác khớp. Một dấu chấm khớp với ‘5’; một dấu chấm khác khớp với ‘X’; và dấu chấm cuối cùng khớp với một dấu chấm.

Thay thế phù hợp

Hãy xem xét câu này cho một chuỗi mục tiêu:

Lồng có các loại chim khác nhau.

Ai đó có thể muốn biết mục tiêu này có chim bồ câu hoặc chim công hoặc đại bàng hay không. Có thể sử dụng mã sau:

P='Cái lồng có những con công thuộc nhiều loại khác nhau.'
nếu như [[ $ str= ~ chim bồ câu|con công|chim ưng]];sau đó
quăng đitìm
khác
quăng đikhông tìm thấy
thì là ở

Đầu ra là, được tìm thấy. Siêu ký tự thay thế, | đã được tuyển dụng. Có thể có hai, ba, bốn và nhiều lựa chọn thay thế. Những gì đã khớp trong mã này là 'peacock'.

Phân nhóm

Trong mẫu sau, dấu ngoặc đơn đã được sử dụng để nhóm các ký tự:

một sân khấu (vũ công)

Nhóm ở đây là một vũ công sân khấu được bao quanh bởi các siêu nhân vật (và). (vũ công) là một nhóm con, trong khi sân khấu (vũ công) là cả nhóm. Hãy xem xét những điều sau:

(Vũ công thật tuyệt vời)

Ở đây, nhóm con hoặc chuỗi con là, vũ công thật tuyệt vời.

Chuỗi con với các bộ phận chung

Một bên liên quan là một người có lợi ích trong một doanh nghiệp. Hãy tưởng tượng một doanh nghiệp với một trang web, cổ phần.com. Hãy tưởng tượng rằng một trong các chuỗi mục tiêu sau nằm trong máy tính:

Trang web, stake.com là dành cho doanh nghiệp;

Có các bên liên quan;

Các bên liên quan làm việc cho cổ phần.com .;

Hãy để bất kỳ chuỗi nào trong số này là mục tiêu. Lập trình viên có thể muốn biết liệu stake.com hoặc bên liên quan có nằm trong chuỗi mục tiêu nào hay không. Mô hình của anh ấy sẽ là:

cổ phần.com | bên liên quan

sử dụng luân phiên.

tiền cược đã được gõ hai lần trong hai từ. Có thể tránh điều này bằng cách nhập mẫu như sau:

cổ phần (.com | chủ sở hữu)

.com | Holder là nhóm con trong trường hợp này.

Lưu ý: việc sử dụng ký tự thay thế trong trường hợp này. cổ phần.com hoặc bên liên quan sẽ vẫn được tìm kiếm. Đầu ra của mã sau được tìm thấy:

P='Trang web, stake.com là dành cho doanh nghiệp.'
nếu như [[ $ str= ~ tiền cược(.với|người giữ) ]];sau đó
quăng đitìm
thì là ở

Chuỗi con phù hợp ở đây là cổ phần.com.

Mảng được xác định trước BASH_REMATCH

BASH_REMATCH là một mảng được xác định trước. Giả sử rằng một mẫu có các nhóm. Toàn bộ nhóm đã khớp, đi vào ô cho chỉ mục 0 của mảng này. Nhóm con đầu tiên được so khớp, đi vào ô cho chỉ mục 1; nhóm con thứ hai đã khớp, đi vào ô cho chỉ mục 2, v.v. Đoạn mã sau đây cho thấy cách sử dụng mảng này:

P='Vũ công sân khấu đã đến.'
nếu như [[ $ str= ~ giai đoạn (vũ công) ]];sau đó
quăng đitìm
thì là ở

tôitrong $ {! BASH_REMATCH [@]};làm
printf '$ {BASH_REMATCH [i]}, '
xong
quăng đi

Đầu ra là:

tìm
vũ công sân khấu, vũ công,

Cả nhóm đều là vũ công sân khấu. Chỉ có một nhóm phụ, đó là vũ công.

Lưu ý: khoảng trống trong mẫu đã bị thoát.

Khớp độc lập chữ hoa / chữ thường

Đối sánh, như đã giải thích ở trên, có phân biệt chữ hoa chữ thường. Đối sánh có thể được thực hiện độc lập với trường hợp. Điều này được minh họa trong đoạn mã sau:

cửa hàng -NSnocasematch

P='Chúng tôi thích âm nhạc hay.'
nếu như [[ $ str= ~ GoOd]];sau đó
quăng đitìm
thì là ở

cửa hàng -unocasematch

Đầu ra là: tìm thấy. Mô hình là, GoOd. Chuỗi con được so khớp là 'tốt'. Lưu ý cách tùy chọn nocasematch đã được bật ở đầu đoạn mã và bị vô hiệu hóa ở cuối đoạn mã.

Chiều dài của một chuỗi

Cú pháp để lấy độ dài của một chuỗi là:

$ {# THÔNG SỐ}

Thí dụ:

P='Chúng tôi thích âm nhạc hay.'
quăng đi $ {# str}

Đầu ra là: 19.

Giảm chuỗi

Các cú pháp để rút gọn chuỗi là:

$ {THÔNG SỐ: OFFSET}
$ {THÔNG SỐ: OFFSET: LENGTH}

trong đó việc đếm OFFSET bắt đầu từ số không.

Ví dụ sau đây cho thấy cách xóa 11 ký tự đầu tiên của một chuỗi:

P='Tôi luôn nhảy theo những bản nhạc hay.'
quăng đi $ {str: 10}

Đầu ra là:

chúc bạn nghe nhạc hay.

Đếm cho CHIỀU DÀI, bắt đầu từ ký tự tiếp theo. Đoạn mã sau cho biết cách một phần trong chuỗi có thể được phép:

P='Tôi luôn nhảy theo những bản nhạc hay.'
quăng đi $ {str: 10: 6}

Đầu ra là:

ance t

11 ký tự đầu tiên đã bị loại bỏ; 6 ký tự tiếp theo được cho phép và các ký tự còn lại sẽ tự động bị xóa.

Tìm kiếm và Thay thế

Khi tìm thấy một chuỗi con, nó có thể được thay thế bằng một chuỗi con khác. Các cú pháp cho điều này là:

ở đâu=$ {PARAMETER / PATTERN / REPLACEMENT}
ở đâu=$ {PARAMETER // PATTERN / REPLACEMENT}
ở đâu=$ {PARAMETER / PATTERN}
ở đâu=$ {THÔNG SỐ // MẪU}

Đối với cú pháp đầu tiên có một dấu gạch chéo lên phía trước, chỉ kết quả khớp đầu tiên được thay thế. Thí dụ:

P='Có một con chuột, một con dơi và một con mèo, trong buồng.'
đúng=$ {str / [cbr] at / big cow}
quăng đi $ str
quăng đi $ ret

Đầu ra là:

Có một con chuột, một con dơi và một con mèo, trong buồng.
Có một con bò lớn, một con dơi và một con mèo, trong buồng.

Đối với cú pháp thứ hai với dấu gạch chéo kép về phía trước, tất cả các lần xuất hiện của khớp sẽ được thay thế. Thí dụ:

P='Có một con chuột, một con dơi và một con mèo, trong buồng.'
đúng=$ {str // [cbr] at / big cow}
quăng đi $ str
quăng đi $ ret

Đầu ra là:

Có một con chuột, một con dơi và một con mèo, trong buồng.
Có một con bò to, một con bò lớn và một con bò lớn, trong buồng.

Đối với cú pháp thứ ba với một dấu gạch chéo về phía trước, không có sự thay thế cho kết quả khớp đầu tiên và duy nhất.

Ngoài ra, chuỗi con đầu tiên được tìm thấy sẽ bị xóa. Thí dụ:

P='Có một con chuột, một con dơi và một con mèo, trong buồng.'
đúng=$ {str / [cbr] at}
quăng đi $ str
quăng đi $ ret

Đối với cú pháp thứ tư với dấu gạch chéo kép về phía trước, không có sự thay thế nào cho tất cả các trận đấu. Ngoài ra, tất cả các chuỗi con được tìm thấy đều bị xóa. Thí dụ:

P='Có một con chuột, một con dơi và một con mèo, trong buồng.'
đúng=$ {str // [cbr] at}
quăng đi $ str
quăng đi $ ret

Đầu ra là:

Có một con chuột, một con dơi và một con mèo, trong buồng.
Có a, a và a, trong buồng.

Phần kết luận

Để kiểm tra xem một chuỗi có một chuỗi con trong Bash hay không, bạn phải sử dụng Khớp mẫu. So khớp mẫu không chỉ diễn ra trong dấu ngoặc kép điều kiện, [[. . . ]]. Nó cũng có thể diễn ra trong việc mở rộng tham số, với $ {. . .}. Với việc mở rộng tham số, có thể thu được một chuỗi con theo các chỉ mục.

Những gì đã được trình bày trong bài viết này là những điểm quan trọng nhất trong Khớp mẫu. Có nhiều! Tuy nhiên, điều mà người đọc nên nghiên cứu tiếp theo, là Filename Expansion.