在 Perl 中比较两个字符串,无论大小写

问题描述 投票:0回答:4

是否有办法比较两个字符串而不管大小写? 例如

"steve" eq "STevE"   <----- these would match
"SHOE" eq "shoe"

看图就知道了

perl compare equals
4个回答
21
投票

是 - 使用

uc()
(大写函数;参见 http://perldoc.perl.org/functions/uc.html

$ perl -e 'print uc("steve") eq uc("STevE"); print "\n";'
1
$ perl -e 'print uc("SHOE") eq uc("shoe"); print "\n";'          
1
$ perl5.8 -e 'print uc("SHOE") eq uc("shoe1"); print "\n";'

$

您显然也可以使用

lc()

如果您希望实际的“eq”运算符不区分大小写,则可能可以使用重载,但我认为这不是您所要求的 - 如果是这种情况,请澄清您的问题。如果您确实想要的话,这也不是一个好主意,恕我直言 - 太脆弱并导致可能难以跟踪和调试的重大错误。

此外,在您只想要相等的特定情况下,这是一种矫枉过正,但 Perl 正则表达式也有与大小写无关的修饰符“i”


16
投票

有几种方法可以做到这一点:

  • 使用

    lc
    uc
    运算符,可将两个字符串分别转换为小写或大写:

    lc "steve" eq lc "STevE";
    
  • 一个简单的正则表达式也可以:

    'steve' =~ /^STevE$/i;
    

6
投票

根据perldoc(http://perldoc.perl.org/functions/fc.html),最好使用

fc("steve") eq fc("STevE")

不要忘记在首次使用

fc
之前添加此行:

use feature 'fc';

0
投票

好吧,这是一个奇怪的错误。

我正在 Perl 中工作,检查字符串中的每个字符,查找是否出现小写字符,后跟完全相同的大写字符。 它在字符串上运行良好。 基本上扩展了我对这个问题的回答。

大写反向引用的正则表达式

我想扩展解决方案以在文件而不是字符串中进行搜索。 相同的代码现在给出错误消息。 尝试捕获错误(lookbehind 正则表达式)会产生错误。 具体来说就是这一行。

$caseInsensitiveMatch = $_ =~ /^$previousLetter$/i;

我尝试了几个不同的输入文件,并注意到有时它会起作用,有时它会给出错误并失败。 我像这样打印出了哪个角色失败了

$caseInsensitiveMatch = $_ =~ /^$previousLetter$/i or die("Previous letter is \"$previousLetter\", current letter is \"$_\"\n");

并且发现当前一个字母是特殊字符时总是会死掉。 在我检查的情况下,它在换行

^L
#
上特别失败。 我搜索了堆栈溢出并找到了这个答案,然后查看了 perldoc 以了解 fc 具体是什么
perldoc -f fc
当我发现这个...

lc($this) eq lc($that)    # Wrong!
uc($this) eq uc($that)    # Also wrong!
$this =~ /^\Q$that\E\z/i  # Right!

然后我注意到,当变量中有特殊字符时,正则表达式可能会将该特殊字符作为命令而不是文字。 但它是不一致的,它只会在某些情况下崩溃,这就是为什么它如此难以捕捉。 基本上一切都说它应该有效,但事实并非如此。

我找到了解决这个问题的两种方法。 第一个是而不是使用

    $caseInsensitiveMatch = $_ =~ /^$previousLetter$/i;

我用过

    $caseInsensitiveMatch = $_ =~ /^\Q$previousLetter\E$/i;

在正则表达式中运行

perldoc perlre
\Q 和 \E 选项意味着以下

\Q          quote (disable) pattern metacharacters until \E
\E          end either case modification or quoted section, think vi

现在,代码可以使用特殊字符

^L
#
以及文件中的任何其他字符(如预期)。 以下解决方案也有效。

$previousLetter = quotemeta($previousLetter);
$caseInsensitiveMatch = $_ =~ /^$previousLetter$/i;

Quotemeta 将确保字符串中的任何特殊字符都被正确转义。 特别是这些字符

\ | ( ) [ { ^ $ * + ? .
。 显然有时 Perl 会隐式地为你转义这些字符,因为如果我手动将字符串设置为类似的东西

my $s = "aSsdD#saAdfF";
my @s = split(//,$s);

分割字符串后即可正常工作。 让我假设当手动输入字符串时,它将转义特殊字符。 但是,如果我从包含特殊字符的文件中手动读取字符串,则除非手动转义字符,否则它将无法正常工作。 它会专门给出这个错误

Unmatched ( in regex; marked by <-- HERE in m/^( <-- HERE $/ at consecutiveCharacters3.pl line 44, <> chunk 1

即使相同的正则表达式在遇到特殊字符之前也可以正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.