Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

perl

I just read about \Q and \E and I am trying to fully undertand them. According to perlre:

\Q quote (disable) pattern metacharacters until \E

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

So I did a couple of tests:

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

If I understand it properly, without \Q it does not evaluate as True because it considers \t as a tab.

Then I used \E and I see no difference:

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

If I give a broader string and pattern containing both literal \t and a tab:

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

It seems to work, because it considers the first \t as fixed string, whereas the second \t is considered a tab.

So is this the way \Q and \E should be used? That is, do we enclose the "clean" strings in between \Q and \E? Is it correct to just use \Q if everything should be treated as literal?

like image 720
fedorqui 'SO stop harming' Avatar asked Sep 07 '25 15:09

fedorqui 'SO stop harming'


2 Answers

\E marks the end, not just of \Q, but other escapes, such as \U. So you would use it when you need the \Q sequence to end. But I think you are overthinking things. \Q is the escape version of quotemeta().

"(foobar" =~ /\Q(fo+bar/    # false, "+" gets escaped
"(foobar" =~ /\Q(\Efo+bar/  # true

I would not say "should be used". If you do not use \E, then \Q continues through your whole pattern.

A more tangible way to see how \E works is to use it with \U:

$ perl -lwe' print "\Ufoobar" '
FOOBAR
$ perl -lwe' print "\Ufoo\Ebar" '
FOObar
like image 129
TLP Avatar answered Sep 10 '25 04:09

TLP


Just like "abc $x def" is the same as "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" is the same as "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

(The difference is just an difference in the indexes in the "pad", the array where lexicals are stored.)

It can also be used in regexp literals.

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

is long for

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

\E can be omitted if it's at the end of the literal.

my $exact_text = "...";
if (/\Q$exact_text/) { ... }
like image 36
ikegami Avatar answered Sep 10 '25 05:09

ikegami