I am trying to place an escape sign before every non-alphanumeric character:
> my $b = "!@#%^||" ~ "/welcome xyz:!@#\$%^&*()|:;.,?/-."
!@#%^||/welcome xyz:!@#$%^&*()|:;.,?/-.
> my $c = $b.subst(/<:!L + :!N - [./-]>/, "\\" ~ $/, :g)
\ \ \ \ \ \ \ /welcome\ xyz\ \ \ \ \ \ \ \ \ \ \ \ \ \ .\ \ /-.
This is the result after running the code the first time. After I run the code the second time, the results is a long string of repeating matches. Similar result if I use the "?" quantifier.
> my $c = $b.subst(/<:!L + :!N - [./-]>/, "\\" ~ $/, :g)
\! @ # % ^ | | : ! @ # $ % ^ & * ( ) | : ; , ?\! @ # % ^ | | : ! @ # $ % ^ & * ( ) | : ; , ?\! @ # % ^ | | # This is truncated long string of undesired result.
Then I tried comb to substitute a single char, but I get multiple errors
> $b.comb.map( {.subst(/<:!L + :!N - [./-]>/, "\\" ~ $/)} )
Use of uninitialized value element of type Any in string context.
Methods .^name, .raku, .gist, or .say can be used to stringify it to something meaningful.
in block at <unknown file> line 1
(\! \! \@ \# \% \^ \| / w e l c o m e \ x y z \ \: \! \@ \# \$ \% \^ \& \* \( \) \| \: . \ \, / - .)
And the result is slightly different if I run the code a second time:
(\ \! \@ \# \% \^ \| / w e l c o m e \ x y z \ \: \! \@ \# \$ \% \^ \& \* \( \) \| \: . \ \, / - .)
Also I cannot join this list:
> $b.comb.map( { if $_.so { .subst(/<:!L + :!N - [./-]>/, "\\" ~ $/)} } ).join
Use of uninitialized value element of type Any in string context.
Methods .^name, .raku, .gist, or .say can be used to stringify it to something meaningful.
in block at <unknown file> line 1
in block <unit> at <unknown file> line 1
The routine tr/// does not do what I try to accomplish.
What is a quick way to place "\" before every non-alnum char in a string? Seems so simple yet so hard. Thanks.
TL;DR Wrap the substitution in a code block (
{ ... }
).A problem when using
$/
withsubst
Quoting
$/
doc:This isn't always true.
Quoting, with suitable added emphasis, from the "Publication" of match variables by Rakudo section of an SO answer I wrote (in a reply to another SO Q you wrote):
The context of the above verbiage was your earlier Q, which wasn't a
subst
's substitution. And I haven't read the compiler code to check what is going on in this new Q's scenario.However, as I read your new SO Q, I immediately felt fairly confident that, when considering the doc's phrasing about
$/
being "set to the result of the last Regex match", and doing so in the context of asubst
call, the updating of$/
would not occur if the substitution passed tosubst
is just a string.To see in more detail what's going on when you don't wrap the substitution in a code block, one can use the
$/
with a code block that does not wrap it but does stillsay
it "en passant":As you'll see if you run that code,
$/
is initially set toNil
.Then, after that statement has been executed, but before the next statement is executed, the
$/
value gets updated. That's why you get a different (but still unhelpful!) result in each subsequent statement. That is to say,$/
is getting updated, but the update is too late for it to work if you just use$/
in a string expression for the substitution rather than putting it inside a code block.A solution when using
subst
in a recent RakudoQuoting again from the same doc:
Again, I haven't checked the compiler source code, but felt somewhat confident that a fresh
$/
is created not just in everyRoutine
but in everyBlock
.¹So I tested wrapping the substitution in a code block, and sure enough that meant the match variable "publication" (updating of
$/
et al) did occur.So I think that's one solution.
Another solution
This is just the same solution in different clothes.
I've used the Q Lang's
q
. This defaults to'...'
string like interpretation of its argument. But one can extensively control its behavior by using options. I've used the:!b
option to turn interpretingb
ackslashes off, and:s
to turn interpreting ofs
calar variables (with$
sigil) on.Footnotes
¹ Modulo optimization of course. That is to say, I'm ignoring optimization that is semantically invisible to user code (I'm ignoring it precisely because it's semantically invisible). This is in stark contrast to the "conservative call" I discussed in the quote from my prior SO answer, by which I meant something akin to a WONTFIX.