Как сравнить две строки в Perl?

178

Как сравнить две строки в Perl?

Я изучаю Perl, этот основной вопрос я нашел здесь, в StackOverflow, и не нашел хорошего ответа, так что я решил спросить.

PJT
источник
3
Сначала вы должны обратиться к превосходной документации, которая поставляется с Perl.
Синан Юнюр
5
Возможно, вы захотите проверить книгу, такую ​​как Learning Perl (которую я в соавторстве). На этот вопрос не было хороших ответов, потому что он очень простой. Учебник поможет вам быстро освоить основы.
Брайан Д. Фой

Ответы:

184

Смотрите perldoc perlop . Используйте lt, gt, eq, ne, и cmpв соответствующих случаях для сравнения строк:

Двоичный eqвозвращает значение true, если левый аргумент по строкам равен правому аргументу.

двоичный ne возвращает значение true, если левый аргумент по строкам не равен правому аргументу.

Двоичный код 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 используется, indexчтобы увидеть, является ли строка подстрокой другой.
Синан Юнюр
3
@Daniel: нет большой практической разницы между = ~ "$ str2" и = ~ / $ str2 / (или просто = ~ $ str2 в этом отношении); index - правильный инструмент, но если по какой-то причине вам нужно использовать регулярное выражение, сделайте = ~ / \ Q $ str2 \ E /.
ysth
1
@IliaRostovtsev !=и neне то же самое, потому что !=и neопределены как разные. Насколько это сложно ?! Будучи оператором сравнения !=чисел , оба его операнда преобразуются в числа perl -E 'say "equal" if not "a" != "b"'.
Синан Юнюр,
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 за исключением того, что возвращаемые значения для eq, gtи ltт. Д. Не верны ... Они возвращают истину или ложь. cmpВозвращает только конкретные числовые значения.
Синан Юнюр,
В Perl 6 используются те же операторы, за исключением того, что legвместо cmpних он используется для общих сравнений.
Брэд Гилберт
17

В дополнение к полному списку операторов сравнения строк в Sinan Ünür, Perl 5.10 добавляет оператор интеллектуального сопоставления.

Оператор умного сопоставления сравнивает два элемента в зависимости от их типа. См. Таблицу ниже для поведения 5.10 (я считаю, что это поведение немного меняется в 5.10.1):

perldoc perlsyn«Умное сопоставление в деталях» :

Поведение интеллектуального соответствия зависит от того, к какому типу относятся его аргументы. Он всегда коммутативен, т.е. $a ~~ $bведет себя так же, как $b ~~ $a. Поведение определяется следующей таблицей: первая применяемая строка в любом порядке определяет поведение совпадения.

  $ a $ b Тип кода, подразумевающего совпадение
  ====== ===== ===================== =============
  (перегрузка превосходит все)

  Код [+] Код [+] ссылочное равенство $ a == $ b   
  Любой код [+] скалярная суб-истина $ b -> ($ a)   

  Хэш Хэш-ключи идентичны [ключи сортировки% $ a] ~~ [ключи сортировки% $ b]
  Существование среза хеш-массива grep {существует $ a -> {$ _}} @ $ b
  Hash Regex grep grep / $ b /, ключи% $ a
  Хеш Любая сущность хеш-записи существует $ a -> {$ b}

  Массив Массивы идентичны [*]
  Массив Regex массив grep grep / $ b /, @ $ a
  Массив Array Num содержит число grep $ _ == $ b, @ $ a 
  Массив Любой массив содержит строку grep $ _ eq $ b, @ $ a 

  Любой undef undefined! Определен $ a
  Любой шаблон регулярного выражения соответствует $ a = ~ / $ b / 
  Code () Code () результаты равны $ a -> () eq $ b -> ()
  Любая Code () истина простого замыкания $ b -> () # игнорирует $ a
  Num numish [!] Числовое равенство $ a == $ b   
  Любое равенство строк Str $ a eq $ b   
  Любое Num числовое равенство $ a == $ b   

  Any Любое равенство строк $ a eq $ b   

+ - это должна быть ссылка на код, чей прототип (если есть) не ""
(подпрограммы с прототипом "" обрабатываются записью Code () внизу) 
* - то есть каждый элемент соответствует элементу с тем же индексом в другом
массив. Если круговая ссылка найдена, мы возвращаемся к ссылочной
равенство.   
! - либо действительное число, либо строка, которая выглядит как число

«Соответствующий код», конечно же, не представляет реальный соответствующий код: он просто объясняет предполагаемое значение. В отличие от grep, оператор интеллектуального сопоставления будет закорачивать всякий раз, когда это возможно.

Пользовательское сопоставление с помощью перегрузки Вы можете изменить способ сопоставления объекта путем перегрузки ~~оператора. Это превосходит обычную семантику умного соответствия. См overload.

Чес. Owens
источник
Это не меняется немного: это меняется радикально. Умное сопоставление чего-либо непростого серьезно нарушено.
Брайан д Фой
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 та же проблема, но по другой причине (и с другими последствиями).
Брент Брэдберн
1

И если вы хотите извлечь различия между двумя строками, вы можете использовать String :: Diff .

Хелен Крейгман
источник
Если вы собираетесь ссылаться на документацию Perl, обычно рекомендуется использовать постоянные ссылки, которые всегда будут ссылаться на новейшую версию модуля. 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
Брэд Гилберт