Como eu comparo duas strings no Perl?

178

Como eu comparo duas strings no Perl?

Estou aprendendo Perl, tive essa pergunta básica pesquisada aqui no StackOverflow e não encontrei uma boa resposta, então pensei em perguntar.

PJT
fonte
3
Você deve primeiro consultar a excelente documentação que acompanha o Perl.
Sinan
5
Você pode querer dar uma olhada em um livro como o Learning Perl (que eu co-autor). Não houve boas respostas para essa pergunta porque é muito básica. Um tutorial o ajudará a entender o básico rapidamente.
Brian D Foy

Respostas:

184

Veja perldoc perlop . Use lt, gt, eq, ne, e cmpconforme apropriado para comparações de strings:

Binário eqretorna true se o argumento da esquerda for igual a string ao argumento da direita.

Binário neretorna true se o argumento da esquerda não for igual ao da direita.

Binário cmpretorna -1, 0 ou 1, dependendo se o argumento esquerdo é menor que, igual a ou maior que o argumento direito.

Binário ~~faz uma correspondência inteligente entre seus argumentos. ...

lt, le, ge, gtE cmpusar a ordem de agrupamento (ordenação) especificado pelo local atual, se uma localidade uso legado (mas não use locale ':not_characters') está em vigor. Veja perllocale . Não os misture com Unicode, apenas com codificações binárias herdadas. Os módulos Unicode :: Collate e Unicode :: Collate :: Locale padrão oferecem soluções muito mais poderosas para problemas de agrupamento.

Sinan Ünür
fonte
9
Apenas mais um, nem por igual.
PJT
4
Você pode mencionar que $ str1 = ~ "$ str2" (não / $ str2 /) verificará se $ str2 é uma subcadeia de $ str1.
227 Daniel C. Sobral
@ Daniel use indexpara ver se uma string é uma substring de outra.
Sinan
3
@ Daniel: não há muita diferença prática entre = ~ "$ str2" e = ~ / $ str2 / (ou apenas = ~ $ str2 para esse assunto); index é a ferramenta certa, mas se você precisar usar um regex por algum motivo, faça = ~ / \ Q $ str2 \ E /.
ysth 24/07/09
1
@IliaRostovtsev !=e nenão são o mesmo, porque !=e nesão definidos para ser diferente. Quão difícil é isso ?! Sendo um operador de comparação numérica, !=converte os dois operandos em números perl -E 'say "equal" if not "a" != "b"'.
Sinan
137
  • cmp Comparar

    'a' cmp 'b' # -1
    'b' cmp 'a' #  1
    'a' cmp 'a' #  0
    
  • eq Igual a

    'a' eq  'b' #  0
    'b' eq  'a' #  0
    'a' eq  'a' #  1
    
  • ne Diferente de

    'a' ne  'b' #  1
    'b' ne  'a' #  1
    'a' ne  'a' #  0
    
  • lt Menor que

    'a' lt  'b' #  1
    'b' lt  'a' #  0
    'a' lt  'a' #  0
    
  • le Menos que ou igual a

    'a' le  'b' #  1
    'b' le  'a' #  0
    'a' le  'a' #  1
    
  • gt Maior que

    'a' gt  'b' #  0
    'b' gt  'a' #  1
    'a' gt  'a' #  0
    
  • ge Melhor que ou igual a

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

Veja perldoc perloppara mais informações.

(Estou simplificando isso um pouco, pois todos cmpretornam um valor que é uma sequência vazia e um valor numericamente zero em vez de 0e um valor que é a sequência '1'e o valor numérico 1. Esses são os mesmos valores que você irá sempre obtenha operadores booleanos em Perl. Você realmente deve usar apenas os valores de retorno para operações numéricas ou booleanas; nesse caso, a diferença não importa.)

Brad Gilbert
fonte
8
Eu gosto mais desta resposta. Exemplos simples e curtos são geralmente mais úteis para iniciantes, do que apenas referências de documentos banais de várias páginas.
Zon
@Zon exceto que os valores de retorno para eq, gt, ltetc não estão corretos ... Eles retornam verdadeiro ou falso. cmpRetorna apenas valores numéricos específicos.
Sinan Ünür 01/04/2015
O Perl 6 usa os mesmos operadores, exceto que, em legvez disso, cmpé usado para comparações genéricas.
23815 Brad Gilbert
17

Além da lista abrangente da Sinan Ünür de operadores de comparação de strings, o Perl 5.10 adiciona o operador de correspondência inteligente.

O operador de correspondência inteligente compara dois itens com base em seu tipo. Veja o gráfico abaixo para o comportamento 5.10 (acredito que esse comportamento esteja mudando um pouco no 5.10.1):

perldoc perlsyn"Correspondência inteligente em detalhes" :

O comportamento de uma correspondência inteligente depende de que tipo de argumento são seus argumentos. É sempre comutativo, ou seja, $a ~~ $bcomporta-se da mesma forma que $b ~~ $a. O comportamento é determinado pela seguinte tabela: a primeira linha que se aplica, em qualquer ordem, determina o comportamento da correspondência.

  $ a $ b Tipo de código de correspondência implícito de correspondência
  ====== ===== ===================== =============
  (sobrecarregar supera tudo)

  Código [+] Código [+] igualdade referencial $ a == $ b   
  Qualquer código [+] sub-verdade escalar $ b -> ($ a)   

  Hash Hash hash keys idênticas [chaves de classificação% $ a] ~~ [chaves de classificação% $ b]
  Grep de existência de fatia de hash de matriz de hash {existe $ a -> {$ _}} @ $ b
  Chave de hash Regex de hash grep grep / $ b /, chaves% $ a
  Hash Existe qualquer entrada de hash $ a -> {$ b}

  Matriz Matrizes da matriz são idênticas [*]
  Matriz Regex matriz grep grep / $ b /, @ $ a
  Matriz Num array contém o número grep $ _ == $ b, @ $ a 
  Matriz Qualquer matriz contém a string grep $ _ eq $ b, @ $ a 

  Qualquer undef undefined! Definiu $ a
  Qualquer padrão Regex corresponde a $ a = ~ / $ b / 
  Os resultados do código () são iguais a $ a -> () eq $ b -> ()
  Qualquer código () simples fechamento verdade $ b -> () # ignorando $ a
  Num numish [!] Igualdade numérica $ a == $ b   
  Qualquer igualdade de string Str $ a eq $ b   
  Qualquer igualdade numérica numérica $ a == $ b   

  Qualquer Qualquer igualdade de string $ a eq $ b   

+ - deve ser uma referência de código cujo protótipo (se presente) não seja ""
(os subs com "" um protótipo são tratados pela entrada 'Code ()' abaixo) 
* - ou seja, cada elemento corresponde ao elemento do mesmo índice no outro
array. Se uma referência circular for encontrada, voltaremos ao referencial
igualdade.   
! - um número real ou uma string que se parece com um número

O "código correspondente" não representa o código correspondente real, é claro: está lá apenas para explicar o significado pretendido. Ao contrário do grep, o operador de partida inteligente irá causar um curto-circuito sempre que possível.

Correspondência personalizada via sobrecarga Você pode alterar a maneira como um objeto é correspondido sobrecarregando o ~~operador. Isso supera a semântica usual de correspondência inteligente. Veja overload.

Chas. Owens
fonte
Não está mudando um pouco: está mudando radicalmente. A correspondência inteligente para qualquer coisa não simples está seriamente quebrada.
22909 brian d foy
1
O link provavelmente deve mudar, pois os documentos foram alterados nesse meio tempo. 5,14.2 atual
Brad Gilbert
10
print "Matched!\n" if ($str1 eq $str2)

O Perl possui operadores separados de comparação de caracteres e de comparação numérica para ajudar na digitação solta no idioma. Você deve ler perlop para todos os diferentes operadores.

Matthew Scharley
fonte
8

O subtexto óbvio desta pergunta é:

por que você não pode simplesmente usar ==para verificar se duas strings são iguais?

O Perl não possui tipos de dados distintos para texto versus números. Ambos são representados pelo tipo "escalar" . Em outras palavras, cadeias são números se você as usar como tal .

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

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

print "3"+4
7

Como texto e números não são diferenciados pelo idioma, não podemos simplesmente sobrecarregar o ==operador para fazer a coisa certa nos dois casos. Portanto, o Perl fornece eqpara comparar valores como texto:

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

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

Em resumo:

  • O Perl não possui um tipo de dados exclusivamente para cadeias de texto
  • use ==ou !=, para comparar dois operandos como números
  • use eqou nepara comparar dois operandos como texto

Existem muitas outras funções e operadores que podem ser usados ​​para comparar valores escalares, mas conhecer a distinção entre essas duas formas é um primeiro passo importante.

Brent Bradburn
fonte
Java tem o mesmo problema, mas por um motivo diferente (e com implicações diferentes).
Brent Bradburn
1

E se você deseja extrair as diferenças entre as duas strings, pode usar String :: Diff .

Helen Craigman
fonte
Se você deseja vincular à documentação do Perl, geralmente é recomendável usar o Permalinks, que sempre será vinculado à versão mais recente do módulo. 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