Làm thế nào để tôi so sánh hai chuỗi trong Perl?


178

Làm thế nào để tôi so sánh hai chuỗi trong Perl?

Tôi đang học Perl, tôi đã có câu hỏi cơ bản này khi tìm nó trên StackOverflow và không tìm thấy câu trả lời hay nên tôi nghĩ tôi sẽ hỏi.


3
Trước tiên bạn nên tham khảo tài liệu tuyệt vời đi kèm với Perl.
Sinan Ünür

5
Bạn có thể muốn xem một cuốn sách như Learning Perl (mà tôi là đồng tác giả). Không có câu trả lời tốt cho câu hỏi này vì nó rất cơ bản. Một hướng dẫn sẽ giúp bạn nhận được những điều cơ bản một cách nhanh chóng.
brian d foy

Câu trả lời:


184

Xem perldoc perlop . Sử dụng lt, gt, eq, ne, và cmpkhi thích hợp để so sánh chuỗi:

Nhị phân eqtrả về true nếu đối số bên trái là chuỗi bằng với đối số bên phải.

Nhị phân netrả về true nếu đối số bên trái là chuỗi không bằng với đối số bên phải.

Nhị phân cmptrả về -1, 0 hoặc 1 tùy thuộc vào việc đối số bên trái có theo chuỗi nhỏ hơn, bằng hoặc lớn hơn đối số bên phải hay không.

Nhị phân ~~thực hiện một sự thông minh giữa các đối số của nó. ...

lt, le, ge, gtcmpsử dụng đối chiếu (loại) theo thứ tự theo quy định của địa phương hiện tại nếu một miền địa phương sử dụng di sản (nhưng không phải use locale ':not_characters') có hiệu lực. Xem perllocale . Không trộn lẫn chúng với Unicode, chỉ với mã hóa nhị phân cũ. Các mô-đun Unicode :: CollateUnicode :: Collate :: Locale tiêu chuẩn cung cấp các giải pháp mạnh mẽ hơn nhiều cho các vấn đề đối chiếu.


9
Chỉ một cái nữa thôi, ne cho không bằng.
PJT

4
Bạn có thể muốn đề cập rằng $ str1 = ~ "$ str2" (không phải / $ str2 /) sẽ kiểm tra xem $ str2 có phải là chuỗi con của $ str1 không.
Daniel C. Sobral

@Daniel sử dụng indexđể xem nếu một chuỗi là một chuỗi con của một chuỗi khác.
Sinan Ünür

3
@Daniel: không có nhiều khác biệt thực tế giữa = ~ "$ str2" và = ~ / $ str2 / (hoặc chỉ = ~ $ str2 cho vấn đề đó); index là công cụ phù hợp, nhưng nếu bạn cần sử dụng regex vì một số lý do, do = ~ / \ Q $ str2 \ E /.
ysth

1
@IliaRostovtsev !=nekhông giống nhau, bởi vì !=neđược định nghĩa là khác nhau. Khó đến thế sao?! Là một toán tử so sánh số, !=chuyển đổi cả toán hạng của nó thành số perl -E 'say "equal" if not "a" != "b"'.
Sinan Ünür

137
  • cmp Đối chiếu

    'a' cmp 'b' # -1
    'b' cmp 'a' #  1
    'a' cmp 'a' #  0
  • eq Tương đương với

    'a' eq  'b' #  0
    'b' eq  'a' #  0
    'a' eq  'a' #  1
  • ne Không bằng

    'a' ne  'b' #  1
    'b' ne  'a' #  1
    'a' ne  'a' #  0
  • lt Ít hơn

    'a' lt  'b' #  1
    'b' lt  'a' #  0
    'a' lt  'a' #  0
  • le Ít hơn hoặc bằng

    'a' le  'b' #  1
    'b' le  'a' #  0
    'a' le  'a' #  1
  • gt Lớn hơn

    'a' gt  'b' #  0
    'b' gt  'a' #  1
    'a' gt  'a' #  0
  • ge Lớn hơn hoặc bằng

    'a' ge  'b' #  0
    'b' ge  'a' #  1
    'a' ge  'a' #  1

Xem perldoc perlopđể biết thêm thông tin.

(Tôi đơn giản hóa tất cả một chút nhưng cmptrả về một giá trị vừa là chuỗi rỗng, vừa là giá trị số 0 thay vì 0và giá trị là cả chuỗi '1'và giá trị số 1. Đây là những giá trị giống nhau bạn sẽ luôn luôn nhận được từ các toán tử boolean trong Perl. Bạn thực sự chỉ nên sử dụng các giá trị trả về cho các phép toán boolean hoặc số, trong trường hợp đó sự khác biệt không thực sự quan trọng.)


8
Tôi thích câu trả lời này hơn. Các ví dụ đơn giản ngắn thường hữu ích hơn cho người mới, hơn là chỉ tham chiếu tài liệu đa cấp banal.
Zon

@Zon ngoại trừ giá trị trả lại cho eq, gt, ltvv là không đúng ... Họ trở về đúng hoặc sai. Chỉ cmptrả về các giá trị số cụ thể.
Sinan ürnür

Perl 6 sử dụng các toán tử tương tự ngoại trừ nó sử dụng legthay vì cmpđược sử dụng để so sánh chung thay thế.
Brad Gilbert

17

Ngoài việc liệt kê toàn diện các toán tử so sánh chuỗi của Sinan, Perl 5.10 thêm toán tử khớp thông minh.

Toán tử kết hợp thông minh so sánh hai mục dựa trên loại của chúng. Xem biểu đồ bên dưới để biết hành vi 5.10 (Tôi tin rằng hành vi này sẽ thay đổi một chút trong 5.10.1):

perldoc perlsyn"Kết hợp thông minh chi tiết" :

Hành vi của một trận đấu thông minh phụ thuộc vào loại đối số của nó. Nó luôn luôn giao hoán, tức là $a ~~ $bhành xử giống như $b ~~ $a. Hành vi được xác định bởi bảng sau: hàng đầu tiên áp dụng, theo thứ tự, xác định hành vi khớp.

  $ a $ b Loại đối sánh Mã phù hợp ngụ ý
  ====== ===== ===================== =============
  (quá tải tất cả mọi thứ)

  Mã [+] Mã [+] đẳng thức tham chiếu $ a == $ b   
  Bất kỳ Mã [+] vô hướng phụ sự thật $ b -> ($ a)   

  Hash Hash Các khóa băm giống hệt nhau [khóa sắp xếp% $ a] ~ ~ [khóa sắp xếp% $ b]
  Sự tồn tại của lát băm Hash Array grep {tồn tại $ a -> {$ _}} @ $ b
  Khóa băm băm Regex grep grep / $ b /, khóa% $ a
  Hash Bất kỳ tồn tại mục băm nào tồn tại $ a -> {$ b}

  Mảng mảng là giống hệt nhau [*]
  Mảng Regex mảng grep grep / $ b /, @ $ a
  Mảng số Num chứa số grep $ _ == $ b, @ $ a 
  Mảng Bất kỳ mảng nào cũng chứa chuỗi grep $ _ eq $ b, @ $ a 

  Bất kỳ định nghĩa không xác định! Xác định $ a
  Bất kỳ mẫu Regex nào khớp với $ a = ~ / $ b / 
  Kết quả Code () Code () bằng $ a -> () eq $ b -> ()
  Bất kỳ mã () sự thật đóng đơn giản $ b -> () # bỏ qua $ a
  Số bằng [!] Số đẳng thức $ a == $ b   
  Bất kỳ chuỗi Str nào bằng $ a eq $ b   
  Bất kỳ số đẳng thức số nào $ a == $ b   

  Bất kỳ chuỗi bằng nào $ a eq $ b   

+ - đây phải là tham chiếu mã có nguyên mẫu (nếu có) không phải là ""
(phụ với nguyên mẫu "" được xử lý bằng mục nhập 'Code ()' xuống dưới) 
* - nghĩa là, mỗi phần tử khớp với phần tử của cùng một chỉ mục trong phần tử khác
mảng. Nếu một tham chiếu tròn được tìm thấy, chúng ta sẽ quay trở lại tham chiếu
bình đẳng.   
! - hoặc là một số thực hoặc một chuỗi trông giống như một số

Tất nhiên, "mã phù hợp" không đại diện cho mã phù hợp thực sự: nó chỉ ở đó để giải thích ý nghĩa dự định. Không giống như grep, toán tử kết hợp thông minh sẽ đoản mạch bất cứ khi nào có thể.

Kết hợp tùy chỉnh thông qua quá tải Bạn có thể thay đổi cách đối tượng được khớp bằng cách nạp chồng ~~toán tử. Điều này hơn hẳn các ngữ nghĩa trận đấu thông minh thông thường. Xem overload.


Nó không thay đổi một chút: nó thay đổi hoàn toàn. Kết hợp thông minh cho bất cứ điều gì không đơn giản bị phá vỡ nghiêm trọng.
brian d foy

1
Liên kết nên thay đổi vì các tài liệu đã thay đổi trong thời gian trung bình. 5.14.2 hiện tại
Brad Gilbert

10
print "Matched!\n" if ($str1 eq $str2)

Perl có các toán tử so sánh chuỗi và so sánh số riêng biệt để giúp gõ phím trong ngôn ngữ. Bạn nên đọc perlop cho tất cả các toán tử khác nhau.


8

Nội dung rõ ràng của câu hỏi này là:

Tại sao bạn không thể sử dụng ==để kiểm tra xem hai chuỗi có giống nhau không?

Perl không có kiểu dữ liệu riêng biệt cho văn bản so với số. Cả hai đều được đại diện bởi loại "vô hướng" . Nói cách khác, chuỗi số nếu bạn sử dụng chúng như vậy .

if ( 4 == "4" ) { print "true"; } else { print "false"; }
true

if ( "4" == "4.0" ) { print "true"; } else { print "false"; }
true

print "3"+4
7

Vì văn bản và số không được phân biệt bởi ngôn ngữ, chúng tôi không thể quá tải ==toán tử để thực hiện đúng cho cả hai trường hợp. Do đó, Perl cung cấp eqđể so sánh các giá trị dưới dạng văn bản:

if ( "4" eq "4.0" ) { print "true"; } else { print "false"; }
false

if ( "4.0" eq "4.0" ) { print "true"; } else { print "false"; }
true

Nói ngắn gọn:

  • Perl không có kiểu dữ liệu dành riêng cho chuỗi văn bản
  • sử dụng ==hoặc !=, để so sánh hai toán hạng dưới dạng số
  • sử dụng eqhoặc ne, để so sánh hai toán hạng dưới dạng văn bản

Có nhiều hàm và toán tử khác có thể được sử dụng để so sánh các giá trị vô hướng, nhưng biết phân biệt giữa hai dạng này là bước đầu tiên quan trọng.


Java có cùng một vấn đề, nhưng vì một lý do khác nhau (và với những hàm ý khác nhau).
Brent Bradburn

1

Và nếu bạn muốn trích xuất sự khác biệt giữa hai chuỗi, bạn có thể sử dụng String :: Diff .


Nếu bạn định liên kết đến tài liệu Perl, thông thường nên sử dụng Permalinks sẽ luôn liên kết với phiên bản mới nhất của mô-đun. search.cpan.org/perldoc/String::Diff search.cpan.org/perldoc?String::Diff p3rl.org/String::Diff metacpan.org/module/String::Diff metacpan.org/pod/String: : Diff Done
Brad Gilbert
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.