Re: Single Quotes - how to avoid any escape processing?
by ww (Archbishop) on Jan 31, 2013 at 19:53 UTC
|
C:\>perl -E "use strict; use warnings; my $str=q(This isn't really an
+answer for URLs like 'http:\\\\www.perlmonks.org!'); say $str;"
This isn't really an answer for URLs like 'http:\\www.perlmonks.org!'
... or maybe this node is an answer, of sorts. Whadda'ya tink?
| [reply] [d/l] |
Re: Single Quotes - how to avoid any escape processing?
by LanX (Saint) on Jan 31, 2013 at 20:04 UTC
|
Welcome to the world of escaping! :)
If you have an end delimiter and you want to allow this end delimiter to appear literally you need to escape it, hence \' => '
But if you're escaping, you're also needing an escape character, which has also to be escaped when used literally, hence \\ => \
And thats it, nothing else needed within the single quotes family of q{} with a free choice of end delimiters.
And now, if you think that perl sucks try emacs lisp, which only supports double quotes! In elisp regexes suffer from a ugly disease called slasheritis².
Luckily you can use heredocs, because there is no delimiter that need to be escaped. And if you don't like the newlines then chomp:
$foo = <<'__HERE__';
\\some.address.or.whatever\subdir\
__HERE__
chomp $foo;
print ">", $foo ,"<"; # >\\some.address.or.whatever\subdir
+\<
I suppose you don't wanna put multiple path in a long heredoc? ¹
So why don't you use a character like / as placeholder?
sub s2b { # slash to backslash
(my $str = shift) =~ tr#/#\\#;
return $str;
}
my $path = s2b '//some.address.or.whatever/subdir/';
Just don't blame Perl for M$ decision to use an escape character for separating paths. =)
update
fixed code for s2b()
footnotes
¹) you could read them into a hash defined by preceded hash keys.
use Data::Dump;
sub parsepath {
my $str=shift;
return split /\s+/,$str;
}
my %path = parsepath <<'__HERE__';
install \\some.address.or.whatever\subdir\
deinstall \\other.address.or.whatever\subdir\
__HERE__
dd \%path;
==>
{
deinstall => "\\\\other.address.or.whatever\\subdir\\",
install => "\\\\some.address.or.whatever\\subdir\\",
}
²) yes, it insults the eyes!!! | [reply] [d/l] [select] |
|
If you have an end delimiter and you want to allow this end delimiter to appear literally you need to escape it
But why is this always considered a necessary feature for a quoting delimiter, trumping all other considerations like avoiding headaches like the OP describes?
For a language that has so many different quoting delimiters as Perl does, I would have expected there to be at least one that would simply drop the pedantic "must allow each and every Unicode character to appear in the string literal" requirement and do no escaping at all.
With a use-case like file paths, it's quite unlikely that not being able to include single quotes (or a similar special-char delimiter) would become a problem.
In addition, I'm not convinced that introducing a separate escape character (in this case, backslash) is technically necessary for implementing single-quoted strings that are supposed to allow single-quotes to appear inside them.
What would prevent the usage of the delimiting character as its own escape character? I.e. two consecutive single-quotes would not terminate a single-quoted string literal, they would be interpreted as one single-quote.
I don't see any reason for ever wanting to put two string literals right next to each other without space or comma in between, so it would not create any syntactical ambiguity. Or am I missing something?
| [reply] |
|
> But why is this always considered a necessary feature for a quoting delimiter, trumping all other considerations like avoiding headaches like the OP describes?
I didn't say it's a necessary, I explained the motivation "If ... you want to allow ...".
> What would prevent the usage of the delimiting character as its own escape character? I.e. two consecutive single-quotes would not terminate a single-quoted string literal
IIRC VB (or VB-Script) does something like this.
> I don't see any reason for ever wanting to put two string literals right next to each other without space or comma in between, so it would not create any syntactical ambiguity.
empty string?
> Or am I missing something?
Perl has already a very complex syntax, adding new extra DWIM exception doesn't make it easier.
What might be easy and meaningful for you can be line noise or just complexity horror for someone else.
For instance see this discussion about the differences between Perl and JS in handling the closing bracket in regex-character classes: Regex: Char-class equivalent for [^].
So in short: Rules have to be kept as simple as possible and backslashing is a well-established notation.
Moritz already mentioned a new way in Perl6, which sounds reasonably simple, so help is on the way for the next version.
EDIT: And for the records: The OP might hate them but I LOVE HERE-DOCS!!!
| [reply] |
|
|
Re: Single Quotes - how to avoid any escape processing?
by moritz (Cardinal) on Jan 31, 2013 at 20:14 UTC
|
So is there a (simple) way to put a string into a scalar variable without any character escaping or processing of the contents of that string at all?
Not that I know of.
If you have large amounts of such data, maybe put them in a __DATA__ section, or into a config file.
That said, Perl 6 has a quoting construct Q'...' that doesn't have any escape sequences. Of course you can't escape the closing delimiter then.
| [reply] [d/l] [select] |
Re: Single Quotes - how to avoid any escape processing?
by tobyink (Canon) on Jan 31, 2013 at 21:06 UTC
|
Although I released it as a joke module, Acme::What does the trick!
use 5.010;
use strict;
use warnings;
use Acme::What;
sub WHAT { +shift }
my $var = what \\foo;
say $var;
I wonder if I should create a slightly saner version along the lines of the Perl 6 Q operator that moritz mentioned?
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
| [reply] [d/l] |
backslashes sometimes unnecessary
by soonix (Canon) on Jan 31, 2013 at 21:26 UTC
|
This isn't perl specific, but I think it's helpful to know that many Windows APIs (including several Microsoft ones) do accept forward slashes as well.
Try
perl -e "print join ' ', glob 'C:/Windows/sys*'"
and enjoy :-)
Although this does not solve your original issue, perhaps it helps alleviate the problem at hand? | [reply] [d/l] |
|
| [reply] |
|
| [reply] |
Re: Single Quotes - how to avoid any escape processing?
by temporal (Pilgrim) on Jan 31, 2013 at 20:59 UTC
|
Thanks for the replies guys.
Yes, it would appear that (for the Googlers) this is not possible. At least not in any simple, straightforward method that I was hoping for.
ww, I did check out that section of the PerlDocs - it told me about what I was expecting. However the reread led me to this (appropriately christened!) section of the same doc which definitively spells everything out about this case, and many others not even considered in this node:
http://perldoc.perl.org/perlop.html#Gory-details-of-parsing-quoted-constructs
This is one of the rare cases where Perl's DWIM philosophy doesn't align with my own, oh well.
A (basic) note - the selected delimiter for q{} is always vulnerable and needful of and being escaped. As you'd expect.
And thanks for the quality snippets LanX, that is probably what I'd end up doing if I had a long list. Fortunately, this time I was just curious about that case =)
Hehe, I certainly don't blame Perl for MS monkey business. The scary part is that I'm starting to get used to it. Boy, sometimes I miss my last position where I worked primarily with Linux-based systems ;)
Of course, moritz offers another good solution for larger volumes of data as well ♥
So thanks again monks. Hopefully this node will stand as an answer, of sorts (heh, ww =D )
Strange things are afoot at the Circle-K.
| [reply] [d/l] |
|
| [reply] [d/l] |
|
Oh yeah, fun stuff. I think at that point I'd start using one of the path parsing/porting modules to handle it all.
iirc File::Path and File::Basename intelligently handle paths with spaces on Windows.
| [reply] |
Re: Single Quotes - how to avoid any escape processing?
by SteveDC (Initiate) on Aug 25, 2019 at 18:10 UTC
|
Although this is an old thread I think it aligns well with a current issue I have whilst processing Windows paths.
I have spent the last hour scouring THE WEB and can't for the life of me find a clean solution to my issue.
Basically what I want to do is split a path into a list of each sub directory, so in its simplest form I tried the following...
$PathOnly = "c:\Dir1\Dir2\Dir3";
@SubDirs = split('\', $PathOnly);
This doesn't work since the \' gets escaped and I end up effectively with a missing '
So, tried to escape the \ with the following...
@SubDirs = split('\\', $PathOnly);
But that also has an error "trailing \ in regex"
As does the following...
@SubDirs = split("\\", $PathOnly);
I even tried the following...
my $SplitAt = "\\";
my @SubDirs = split($SplitAt, $PathOnly);
Whilst this doesn't have syntax errors, and $SplitAt seems to get theexpected "\" it fails on the execution of the split with the same "trailing \ in regex", just at execution time this time.
Now... just for kicks and giggles I tried the following...
my $SplitAt = "\\\\";
my @SubDirs = split($SplitAt, $PathOnly);
BOOM !!! I get the correct result (I actually thought of this whilst typing the comment but figured the info might help someone at some point in time)
So, then I tried the following...
my @SubDirs = split("\\\\", $PathOnly);
This also worked as I wanted.
So, my original question has changed from "How do I split a Windows path on \ ?" to "Why does "\\\\" work in the split statement?
I have been working with Perl on and off for about 20 years but I am by no means an expert, but this conundrum completely confuses me.
BR,
Steve
| [reply] [d/l] [select] |
|
@SubDirs = split(/\\/, $PathOnly);
But maybe you want to use File::Spec instead, or Path::Tiny?
my @SubDirs = File::Spec->splitdir( $PathOnly );
| [reply] [d/l] [select] |
|
c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le
"print '\\';
print '\\\\';
print qq{\\};
print qq{\\\\};
;;
print qr{\\};
my $bb = '\\\\';
print qr{$bb};
;;
my $PathOnly = 'c:\Dir1\Dir2\Dir3';
;;
my @SubDirs = split(m/\\/, $PathOnly);
dd \@SubDirs;
;;
@SubDirs = split($bb, $PathOnly);
dd \@SubDirs;
"
\
\\
\
\\
(?-xism:\\)
(?-xism:\\)
["c:", "Dir1", "Dir2", "Dir3"]
["c:", "Dir1", "Dir2", "Dir3"]
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
|
... your $PathOnly is in double quotes, so the backslashes there are i
+nterpreted as escape sequences.
SteveDC: Ah, yes!
c:\@Work\Perl\monks>perl -wMstrict -le
"my $PathOnly = qq{c:\Dir1\Dir2\taint_so};
print qq{>$PathOnly<};
"
Unrecognized escape \D passed through at -e line 1.
Unrecognized escape \D passed through at -e line 1.
>c:Dir1Dir2 aint_so<
Don't know how you missed the warnings. You do have warnings enabled, right? Right?
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |