ฉันจะเปรียบเทียบสองสตริงใน Perl ได้อย่างไร


178

ฉันจะเปรียบเทียบสองสตริงใน Perl ได้อย่างไร

ฉันกำลังเรียนรู้ Perl ฉันมีคำถามพื้นฐานนี้ค้นหาได้ที่นี่ใน StackOverflow และไม่พบคำตอบที่ดีดังนั้นฉันคิดว่าฉันจะถาม


3
ก่อนอื่นคุณควรศึกษาเอกสารที่ยอดเยี่ยมที่มาพร้อมกับ Perl
Sinan Ünür

5
คุณอาจต้องการตรวจสอบหนังสือเช่นLearning Perl (ซึ่งฉันร่วมเขียน) ไม่มีคำตอบที่ดีสำหรับคำถามนี้เพราะพื้นฐานมาก บทช่วยสอนจะช่วยให้คุณรับข้อมูลเบื้องต้นได้อย่างรวดเร็ว
brian d foy

คำตอบ:


184

ดูperldoc perlop การใช้งานlt, gt, eq, neและcmpตามความเหมาะสมสำหรับการเปรียบเทียบสตริง:

eqผลตอบแทนไบนารีเป็นจริงถ้าอาร์กิวเมนต์ด้านซ้ายเป็นสตริงเท่ากับอาร์กิวเมนต์ที่ถูกต้อง

neผลตอบแทนแบบไบนารีจริงถ้าอาร์กิวเมนต์ซ้ายเป็นสตริงตามตัวอักษรไม่เท่ากับอาร์กิวเมนต์ที่เหมาะสม

cmpผลตอบแทนแบบไบนารี-1, 0 หรือ 1 ขึ้นอยู่กับว่าอาร์กิวเมนต์ซ้ายเป็นสตริงตามเข็มนาฬิกาน้อยกว่าเท่ากับหรือมากกว่าอาร์กิวเมนต์ขวา

ไบนารี~~จะจับคู่สมาร์ทระหว่างอาร์กิวเมนต์ ...

lt, le, ge, gtและcmpใช้เปรียบเทียบ (เรียงลำดับ) การสั่งซื้อโดยระบุสถานที่ปัจจุบันมีการใช้สถานที่มรดก ( แต่ไม่use locale ':not_characters') อยู่ในผล ดูperllocale อย่าผสมสิ่งเหล่านี้กับ Unicode เท่านั้นด้วยการเข้ารหัสไบนารีดั้งเดิม มาตรฐานUnicode :: CollateและUnicode :: Collate :: Localeนำเสนอโซลูชันที่มีประสิทธิภาพยิ่งขึ้นสำหรับการเปรียบเทียบปัญหา


9
อีกเพียงหนึ่งไม่เท่ากัน
PJT

4
คุณอาจต้องการพูดถึงว่า $ str1 = ~ "$ str2" (ไม่ใช่ / $ str2 /) จะตรวจสอบว่า $ str2 เป็นสตริงย่อยของ $ str1
Daniel C. Sobral

@Daniel ใช้indexเพื่อดูว่าสตริงเป็นซับสตริงของอีกอันหรือไม่
Sinan Ünür

3
@Daniel: ไม่มีความแตกต่างในทางปฏิบัติระหว่าง = ~ "$ str2" และ = ~ / $ str2 / (หรือเพียง = ~ $ str2 สำหรับเรื่องนั้น); ดัชนีเป็นเครื่องมือที่เหมาะสม แต่ถ้าคุณต้องการใช้ regex ด้วยเหตุผลบางประการให้ทำ = ~ / \ Q $ str2 \ E /
ysth

1
@IliaRostovtsev !=และneไม่เหมือนกันเพราะ!=และneกำหนดให้แตกต่างกัน นั่นมันยากแค่ไหน! เป็นตัวดำเนินการเปรียบเทียบตัวเลขแปลงตัวถูกดำเนินการทั้งสองไปยังหมายเลข!= perl -E 'say "equal" if not "a" != "b"'
Sinan Ünür

137
  • cmp เปรียบเทียบ

    'a' cmp 'b' # -1
    'b' cmp 'a' #  1
    'a' cmp 'a' #  0
  • eq เท่ากับ

    'a' eq  'b' #  0
    'b' eq  'a' #  0
    'a' eq  'a' #  1
  • ne ไม่เท่ากับ

    'a' ne  'b' #  1
    'b' ne  'a' #  1
    'a' ne  'a' #  0
  • lt น้อยกว่า

    'a' lt  'b' #  1
    'b' lt  'a' #  0
    'a' lt  'a' #  0
  • le น้อยกว่าหรือเท่ากับ

    'a' le  'b' #  1
    'b' le  'a' #  0
    'a' le  'a' #  1
  • gt มากกว่า

    'a' gt  'b' #  0
    'b' gt  'a' #  1
    'a' gt  'a' #  0
  • ge มากกว่าหรือเท่ากับ

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

ดูperldoc perlopข้อมูลเพิ่มเติม

(ฉันจะทำให้มันง่ายขึ้นเล็กน้อย แต่ให้cmpคืนค่าที่เป็นทั้งสตริงว่างและค่าตัวเลขศูนย์แทน0และค่าที่เป็นทั้งสตริง'1'และค่าตัวเลข1นี่คือค่าเดียวกันกับที่คุณจะ ได้รับจากตัวดำเนินการบูลีนใน Perl เสมอคุณควรใช้ค่าส่งคืนสำหรับการดำเนินการบูลีนหรือตัวเลขซึ่งในกรณีนี้ความแตกต่างไม่สำคัญเลย)


8
ฉันชอบคำตอบนี้มากกว่า ตัวอย่างง่ายๆสั้น ๆ มักจะเป็นประโยชน์สำหรับมือใหม่มากกว่าการอ้างอิงเอกสารทวีคูณเท่านั้น
Zon

@Zon ยกเว้นว่าค่าตอบแทนสำหรับeq, gt, ltฯลฯ ไม่ถูกต้อง ... พวกเขากลับมาจริงหรือเท็จ เพียงcmpส่งกลับค่าตัวเลขที่เฉพาะเจาะจง
Sinan Ünür

Perl 6 ใช้โอเปอเรเตอร์เดียวกันยกเว้นที่ใช้legแทนcmpซึ่งใช้สำหรับการเปรียบเทียบทั่วไปแทน
Brad Gilbert

17

นอกจากนี้ในรายการ Sinan Ünürที่ครอบคลุมของตัวดำเนินการเปรียบเทียบสตริง Perl 5.10 จะเพิ่มตัวดำเนินการจับคู่ที่ชาญฉลาด

ตัวดำเนินการจับคู่แบบอัจฉริยะเปรียบเทียบสองรายการตามประเภทของพวกเขา ดูแผนภูมิด้านล่างสำหรับพฤติกรรม 5.10 (ฉันเชื่อว่าพฤติกรรมนี้เปลี่ยนแปลงเล็กน้อยใน 5.10.1):

perldoc perlsyn"รายละเอียดการจับคู่สมาร์ท" :

พฤติกรรมของการจับคู่ที่ชาญฉลาดขึ้นอยู่กับประเภทของข้อโต้แย้ง มันก็มักจะสับเปลี่ยนคือพฤติกรรมเช่นเดียวกับ$a ~~ $b $b ~~ $aพฤติกรรมจะถูกกำหนดโดยตารางต่อไปนี้: แถวแรกที่ใช้ในลำดับใดก็ตามจะกำหนดพฤติกรรมการจับคู่

  $ a $ b ประเภทการจับคู่รหัสการจับคู่โดยนัย
  ====== ===== ===================== =============
  (เกินพิกัดทุกอย่างสำคัญกว่า)

  รหัส [+] รหัส [+] ความเท่าเทียมกันในการอ้างอิง $ a == $ b   
  รหัสใด ๆ [+] เซนต์คิตส์และเนวิส $ b -> ($ a)   

  Hash Hash hash keys เหมือนกัน [sort keys% $ a] ~~ [keys keys% $ b]
  Hash Array grep hash slice ดำรงอยู่ grep {ดำรงอยู่ $ a -> {$ _}} @ $ b
  Hash Regex แฮชคีย์ grep grep / $ b /, คีย์% $ a
  Hash มีรายการแฮชใด ๆ อยู่ $ a -> {$ b}

  Array Array Array นั้นเหมือนกัน [*]
  Array Regex array grep grep grep / $ b /, @ $ a
  อาร์เรย์ Arum Num มีหมายเลข grep $ _ == $ b, @ $ a 
  อาร์เรย์ใด ๆ ที่มีสตริง grep $ _ eq $ b, @ $ a 

  undef ใด ๆ ไม่ได้กำหนด! กำหนด $ a
  รูปแบบ Regex ใด ๆ ตรงกับ $ a = ~ / $ b / 
  โค้ด () โค้ด () ผลลัพธ์เท่ากับ $ a -> () eq $ b -> ()
  รหัสใด ๆ () ความจริงปิดง่าย ๆ $ b -> () # ไม่สนใจ $ a
  Num numish [!] ความเท่าเทียมกันของตัวเลข $ a == $ b   
  สตริงสตริเท่าเทียมกัน $ a eq $ b   
  ความเท่าเทียมกันของตัวเลข Num ใด ๆ $ a == $ b   

  สตริงใด ๆ เท่าเทียมกัน $ a eq $ b   

+ - นี่จะเป็นการอ้างอิงรหัสที่มีต้นแบบ (ถ้ามี) ไม่ใช่ ""
(หมวดย่อยที่มีต้นแบบ "" ถูกจัดการโดยรายการ 'Code ()' ต่ำลง) 
* - นั่นคือแต่ละองค์ประกอบตรงกับองค์ประกอบของดัชนีเดียวกันในอีกองค์ประกอบหนึ่ง
แถว หากพบการอ้างอิงแบบวงกลมเราจะถอยกลับไปอ้างอิง
ความเท่าเทียมกัน   
! - เป็นจำนวนจริงหรือสตริงที่มีลักษณะเป็นตัวเลข

แน่นอนว่า "รหัสการจับคู่" ไม่ได้แสดงถึงรหัสการจับคู่ที่แท้จริงแน่นอนมีเพียงเพื่ออธิบายความหมายที่ต้องการ ซึ่งแตกต่างจาก grep ตัวดำเนินการจับคู่ที่ชาญฉลาดจะลัดวงจรเมื่อใดก็ตามที่ทำได้

การจับคู่ที่กำหนดเองผ่านการบรรทุกเกินพิกัดคุณสามารถเปลี่ยนวิธีการที่วัตถุถูกจับคู่โดยมากไป~~ประกอบการ สิ่งนี้สำคัญกว่าซีแมนทิกส์การจับคู่ปกติ overloadดู


มันไม่เปลี่ยนแปลงเล็กน้อย: มันเปลี่ยนไปอย่างสิ้นเชิง การจับคู่ที่ชาญฉลาดสำหรับสิ่งที่ไม่เรียบง่ายนั้นเสียอย่างจริงจัง
brian d foy

1
ลิงก์ควรเปลี่ยนแปลงอย่างน่าเชื่อถือเนื่องจากเอกสารมีการเปลี่ยนแปลงในเวลาเฉลี่ย 5.14.2 ปัจจุบัน
แบรดกิลเบิร์ต

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

Perl มีการเปรียบเทียบสตริงแยกและตัวดำเนินการเปรียบเทียบตัวเลขเพื่อช่วยในการพิมพ์หลวมในภาษา คุณควรอ่านperlopสำหรับตัวดำเนินการต่าง ๆ ทั้งหมด


8

ข้อความที่ชัดเจนของคำถามนี้คือ:

ทำไมคุณไม่สามารถใช้==เพื่อตรวจสอบว่าสองสายเหมือนกันหรือไม่

Perl ไม่มีประเภทข้อมูลที่แตกต่างกันสำหรับข้อความและตัวเลข พวกเขาทั้งสองเป็นตัวแทนโดยแบ่งตามชนิด"สเกลาร์" วางวิธีอื่นสตริงเป็นตัวเลขถ้าคุณใช้พวกเขาเป็นเช่นนี้

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

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

print "3"+4
7

เนื่องจากข้อความและตัวเลขไม่ได้มีความแตกต่างกันในภาษาเราจึงไม่สามารถโอเวอร์โหลด==โอเปอเรเตอร์เพื่อทำสิ่งที่ถูกต้องสำหรับทั้งสองกรณี ดังนั้น Perl ให้eqเปรียบเทียบค่าเป็นข้อความ:

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

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

ในระยะสั้น:

  • Perl ไม่มีประเภทข้อมูลสำหรับสตริงข้อความโดยเฉพาะ
  • ใช้==หรือ!=เพื่อเปรียบเทียบตัวถูกดำเนินการสองตัวเป็นตัวเลข
  • ใช้eqหรือneเพื่อเปรียบเทียบตัวถูกดำเนินการสองตัวเป็นข้อความ

มีฟังก์ชั่นและตัวดำเนินการอื่น ๆ อีกมากมายที่สามารถใช้เพื่อเปรียบเทียบค่าสเกลาร์ได้


Java มีปัญหาเดียวกัน แต่ด้วยเหตุผลที่แตกต่างกัน (และมีความหมายต่างกัน)
Brent Bradburn

1

และถ้าคุณต้องการที่จะแยกความแตกต่างระหว่างสองสายที่คุณสามารถใช้String :: Diff


หากคุณกำลังจะเชื่อมโยงไปยังเอกสาร Perl มักจะแนะนำให้ใช้ Permalinks ซึ่งมักจะเชื่อมโยงไปยังโมดูลรุ่นใหม่ล่าสุด 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.