Perl 中的 \Q 是什么?总是需要使用 \E 吗?

What is \Q in Perl? Is it always necessary to use \E?

我刚刚阅读了有关 \Q\E 的内容,我正试图完全理解它们。根据 perlre:

\Q quote (disable) pattern metacharacters until \E

\E end either case modification or quoted section, think vi

所以我做了几个测试:

$ perl -e 'print "hello\n" if "he\tllo" =~ /\Q\t/'
hello
$ perl -e 'print "hello\n" if "he\tllo" =~ /\t/'
$ 

如果我理解正确,没有 \Q 它不会评估为 True 因为它将 \t 视为制表符。

然后我用了\E,我看不出有什么区别:

$ perl -e 'print "hello\n" if "he\tllo" =~ /\Q\t\E/'
hello

如果我给出更广泛的字符串和模式,同时包含文字 \t 和制表符:

$ perl -e 'print "hello\n" if "he\tl\tlo" =~ /\Q\t\E.*\t/'
hello

它似乎有效,因为它将第一个 \t 视为固定字符串,而第二个 \t 被视为制表符。

那么\Q\E是不是应该这样使用呢?也就是说,我们是否将 "clean" 字符串包含在 \Q\E 之间?如果一切都应该被视为文字,只使用 \Q 是否正确?

\E 标记结束,不仅仅是 \Q,还有其他转义符,例如 \U。所以当你需要 \Q 序列结束时你会使用它。但我认为你想多了。 \Qquotemeta().

的转义版本
"(foobar" =~ /\Q(fo+bar/    # false, "+" gets escaped
"(foobar" =~ /\Q(\Efo+bar/  # true

我不会说"should be used"。如果您不使用 \E,则 \Q 会继续整个模式。

了解 \E 工作原理的更具体方法是将其与 \U 一起使用:

$ perl -lwe' print "\Ufoobar" '
FOOBAR
$ perl -lwe' print "\Ufoo\Ebar" '
FOObar

如果后面没有危险,则不需要最后的 \E。我不确定这种行为是否记录在案,但我已经见过很多次了。

看看变量插值如何与 \Q 一起玩也很有趣:

perl -E '$x = "lo$"; say "hello" =~ /$x/'
1

perl -E '$x = "lo$"; say "hello" =~ /\Q$x/'

# ^
# | empty line here.

另见 quotemeta

就像"abc $x def""abc ".$x." def"一样

$ diff -u0 \
   <( perl -MO=Concise,-exec -E'$_ = "abc $x def";'     2>&1 ) \
   <( perl -MO=Concise,-exec -E'$_ = "abc ".$x." def";' 2>&1 ) \
      && echo "same"
same

"abc \Q$x\t\E def" 等同于 "abc ".quotemeta($x."\t")." def"

$ diff -u0 \
   <( perl -MO=Concise,-exec -E'$_ = "abc \Q$x\t\E def";'               2>&1 ) \
   <( perl -MO=Concise,-exec -E'$_ = "abc ".quotemeta($x."\t")." def";' 2>&1 ) \
      && echo "same"
--- /dev/fd/63  2015-01-06 11:22:49.564061341 -0500
+++ /dev/fd/62  2015-01-06 11:22:49.564061341 -0500
@@ -7,3 +7,3 @@
-6  <2> concat[t3] sK/2
-7  <1> quotemeta[t4] sK/1
-8  <2> concat[t5] sK/2
+6  <2> concat[t4] sK/2
+7  <1> quotemeta[t5] sK/1
+8  <2> concat[t6] sK/2
@@ -11 +11 @@
-a  <2> concat[t6] sKS/2
+a  <2> concat[t7] sKS/2

(不同之处只是 "pad" 中存储词法的数组中的索引不同。)

它也可以用在正则表达式中。

my $exact_text = "...";
my $pat = quotemeta($exact_text);
if (/$pat/) { ... }

my $exact_text = "...";
if (/\Q$exact_text\E/) { ... }

\E如果在字面量的末尾可以省略。

my $exact_text = "...";
if (/\Q$exact_text/) { ... }