How do I fix "Unescaped left brace in regex is deprecated" error in Parse::Yapp? - perl

The Parse::Yapp currently shiping on Ubuntu 16.04 (xenial) is slightly behind perl in that it uses unescaped '{'s in regular expressions. The error message indicates that it's in YappParse.yp which doesn't exist. In the interest of patching it locally until a new version of Parse::Yapp comes down the pipe, what template file is it in?
{yapp}
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/\G{ <-- HERE / at YappParse.yp line 288.
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/\G%{ <-- HERE / at YappParse.yp line 315.

Parse::Yapp hasn't had a release since 2001. I wouldn't hold my breath. Since it's effectively unmaintained I'd recommend either moving whatever you're using off of it or taking over maintenance. Consider something like Pegex or Regexp::Grammars instead.
Fortunately this problem has been reported twice, both contain patches. See rt.cpan.org 114776 and rt.cpan.org 10668.
Maintenance has been picked up and 1.20 appears to fix the problem.

perldb's stack trace revealed (or implied that) the file is Parse/Yapp/Parse.pm. Here's a patch:
diff -u /usr/share/perl5/Parse/Yapp/Parse.pm{~,}
--- /usr/share/perl5/Parse/Yapp/Parse.pm~ 2001-05-20 07:19:57.000000000 -0400
+++ /usr/share/perl5/Parse/Yapp/Parse.pm 2016-09-18 02:12:09.116799976 -0400
## -880,7 +880,7 ##
return($1, [ $1, $lineno[0] ]);
};
- $$input=~/\G{/gc
+ $$input=~/\G\{/gc
and do {
my($level,$from,$code);
## -907,7 +907,7 ##
and return('START',[ undef, $lineno[0] ]);
$$input=~/\G%(expect)/gc
and return('EXPECT',[ undef, $lineno[0] ]);
- $$input=~/\G%{/gc
+ $$input=~/\G%\{/gc
and do {
my($code);
Hopefully this will save others some detective work.

This also occurs if you are calling a ksh shell script (such as print) from a non-ksh shell (such as bash).

Related

ruamel.yaml.cmd rt breaks lists, if containing long string, or hash

I just notices that the command line tool, called like this: "ruamel.yaml.cmd rt --save $YAML_FILE", will break lists that either contain long strings, or hashes:
Example list containing a hash:
Source:
telegraf::inputs:
cpu:
- percpu: true
totalcpu: true
report_active: true
output:
telegraf::inputs:
cpu:
- percpu: true
totalcpu: true
report_active: true
example list containing long string:
source:
rsyslog::config::snippets:
00_forward:
ensure: 'present'
lines:
- 'if $syslogfacility != 1 then {'
- 'action(Name="collector-syslog" Type="omfwd" Target="%{hiera("rsyslog_server")}" Port="514" Action.ResumeInterval="5" Protocol="tcp")'
- '}'
output:
rsyslog::config::snippets:
00_forward:
ensure: present
lines:
- if $syslogfacility != 1 then {
- action(Name="collector-syslog" Type="omfwd" Target="%{hiera("rsyslog_server")}"
Port="514" Action.ResumeInterval="5" Protocol="tcp")
- '}'
I already created a bug report for this, but it was deleted with a comment pointing to https://yaml.readthedocs.io/en/latest/example.html?highlight=indent#output-of-dump-as-a-string.
But I am not sure how this code snipped should help me with the command line tool.
Or is the tool deprecated, and I have to roll my own?
The automatic detection of the indent seems incorrect for your input, as that input is inconsistent (your mappings are indented 2 positions and your sequences 4 positions with an offset for the block sequence indicator of 2). ruamel.yaml.cmd as on PyPI doesn't support different indentation levels for sequences and mappings (ruamel.yaml didn't when that was written, it does now).
Apart from that you cannot set the line width for the output in ruamel.yaml.cmd for older versions ( before 2020-12-01), and those versions are using the default 80 characters for the wrapping.
I recommend you upgrade to 0.5.6 and use the command line options:
yaml rt --indent 2 --width 1024 --save <yourfile>
The appropriate repository for ruamel.yaml.cmd is https://sourceforge.net/p/ruamel-yaml-cmd/code/ci/default/tree/ . A bug report on ruamel.yaml which can only be used from a Python program, should include the minimal source code of the program that reproduces the error, and if not provided, issues will be removed as announced on its create issue page.

What is the Powershell ${^} variable?

I recently learned that you can use special characters in PowerShell variables, e.g.: ${hello world!}, but then I stumbled across this:
${^}
What does it do? I first thought it referenced the newest created variable, but it does other stuff I haven't really figured out.
The documentation says:
Contains the first token in the last line received by the session.
Examples:
dir c:\windows 🡒 dir
0..9 🡒 0
&{ dir } 🡒 &
It was likely introduced to get the last command used (dir, copy, rm, ...), but in reality that will only work for the most simplest cases, and thus it's not very useful.
The corresponding $$ returns the last token from the last line.
Note: The curly braces {} are only necessary for variable names containing characters which are not allowed in variables, except automatic variables (look here). In this case, you can omit them:
$^
It shows the first word/token in the last executed command.

When I run a file which is begin with "#!/usr/bin/perl -w", I get a error: "syntax error at line 153, near "=~ ?""

When I run a file which is begin with #!/usr/bin/perl -w, I get a error:
syntax error at line 153, near "=~ ?"
I try to add "#!/bin/bash", this error is not append, but I get another
error:
"line 34: syntax error near unexpected token `('"
line 153 in my file:
($output_volume =~ ?^([\S]+).mnc?) && ($base_name = $1) ||
die "sharpen_volume failed: output volume does not appear to be"
." a minc volume.\n";
line34 in my file:
use MNI::Startup qw(nocputimes);
$output_volume =~ ?^([\S]+).mnc?
This used to be valid perl and thus might appear in old code and instructional material.
From perlop:
In the past, the leading m in m?PATTERN? was optional, but omitting it would produce a deprecation warning. As of v5.22.0, omitting it produces a syntax error. If you encounter this construct in older code, you can just add m.
That is Perl code so the first error message is meaningful.
With delimiters other than // in the match operator you must have the explicit m for it, so
$output_volume =~ m?^([\S]+).mnc?
It is only with // delimiters that the m may be omitted; from Regex Quote-Like Operators (perlop)
If "/" is the delimiter then the initial m is optional.
See perlretut for a tutorial introduction to regex and perlre for reference.
Also note that the particular delimiters of ? trigger specific regex behavior in a special case. This is discussed by the end of the documentation section in perlop linked above.
You already have two answers that explain the problem.
? ... ? is no longer valid syntax for a match operator. You need m? ... ? instead.
Until Perl 5.22, your syntax generated a warning. Now it's a fatal error (which is what you are seeing). So I assume you're now running this on a more recent version of Perl.
There are, however, a few other points it is probably worth making.
You say you tried to investigate this by changing the first line of your file from #!/usr/bin/perl -w to #!/bin/bash. I'm not sure how you think this was going to help. This line defines the program that is used to run your code. As you have Perl code, you need to run it with Perl. Trying to run it with bash is very unlikely to be useful.
The m? ... ? (or, formerly, ? ... ?) syntax triggers an obscure and specialised behaviour. It seems to me that this behaviour isn't required in your case, so you can probably change it to the more usual / ... /.
Your regex contains an unescaped dot character. Given that you seem to be extracting the basename from a filename that has an extension, it seems likely that this should be escaped (using \.) so that it matches an actual dot (rather than any character).
If you are using this code to extract a file's basename, then using a regex probably isn't the best approach. Perhaps take a look at File::Basename instead.

How to resolve PintOS unrecognized character \x16

I downloaded and set up PintOS and the dependencies on my home computer, but when I try to run pintos run alarm-multiple, I get the error:
Unrecognized character \x16; marked by <-- HERE after if ($<-- HERE near column 7 at ~/code/pintos/src/utils/pintos line 911.
That line has ^V on it, the synchronous idle control character. I haven't been able to find any information on this problem; it seems like I'm the only one experiencing it.
I have Perl v5.26.0 installed.
Use of literal control characters in variable names was deprecated in Perl 5.20:
Literal control characters in variable names
This deprecation affects things like $\cT, where \cT is a literal control (such as a NAK or NEGATIVE ACKNOWLEDGE character) in the source code. Surprisingly, it appears that originally this was intended as the canonical way of accessing variables like $^T, with the caret form only being added as an alternative.
The literal control form is being deprecated for two main reasons. It has what are likely unfixable bugs, such as $\cI not working as an alias for $^I, and their usage not being portable to non-ASCII platforms: While $^T will work everywhere, \cT is whitespace in EBCDIC. [perl #119123]
The code causing this problem was fixed in PintOS with this commit in 2016:
committer Ben Pfaff <blp#cs.stanford.edu>
Tue, 9 Feb 2016 04:47:10 +0000 (20:47 -0800)
Modern versions of Perl prefer a caret in variable names over literal
control characters and issue a warning if the control character is used.
This fixes the warning.
diff --git a/src/utils/pintos b/src/utils/pintos
index 1564216..2ebe642 100755 (executable)
--- a/src/utils/pintos
+++ b/src/utils/pintos
## -912,7 +912,7 ## sub get_load_average {
# Calls setitimer to set a timeout, then execs what was passed to us.
sub exec_setitimer {
if (defined $timeout) {
- if ($\16 ge 5.8.0) {
+ if ($^V ge 5.8.0) {
eval "
use Time::HiRes qw(setitimer ITIMER_VIRTUAL);
setitimer (ITIMER_VIRTUAL, $timeout, 0);
Perl 5.26 made it a fatal error to use literal control characters in variable names.
The way you fix it is by ensuring that you are using the most recent version of pintOS. The command git clone git://pintos-os.org/pintos-anon ought to do it.
^V is a perlvar. For reasons unknown to me, it was encoded not as ^ V, but as a single unicode character, which caused the program to fail.

Getting Error of Modification of a read-only value attempted

I am trying to select the below value from database:
Reporting that one of #its many problems had been the recent# extended
sales slump in women's apparel, the seven-store retailer said it would
start a three-month liquidation sale in all of its stores.~(A) its
many problems had been the recent~(B) its many problems has been the
recently~(C) its many problems is the recently~(D) their many problems
is the recent~(E) their many problems had been the recent~
i am selecting this value in variable $ques and then selecting a text as below:
$ques=~s/^(.*?)\#(.*?)\#(.*?)$/$2/;
Now, while replacing the ~ character in the string by
$3=~s/~/\n/g; ---->line 171
and running the script, I am getting one error as:
Modification of a read-only value attempted at main.pl line 171
I want to replace all the ~ character with '\n' and print the final value. Please suggest how to do it.
*I have researched this on net, but got confused that how to handle these read only variables.
You've already got a good explanation of the problem from José Castro. But there's another solution if you're using a recent-ish version of Perl (Update: having checked more carefully, I find that means 5.14+). The /r argument to the substitution operator will copy your string, make the substitution on the copy and then return that altered value.
So you could write:
my $new_value = $3 =~ s/~/\n/rg;
It sounds like what you really want in this case is split rather than regular expression capture groups:
my #parts = split(/#/, $ques);
$parts[2] =~ s/~/\n/g;
It makes the intent of your code clearer since you are, in fact, splitting on # symbols.
Just like you say, the special variables $1, $2, etc., are read-only, and that means that you can't perform that substitution on them.
Performing the substitution on $ques will do what you need:
$ques =~ s/~/\n/g;
print $ques;
Do note that in the earlier substitution that you're performing on $ques you're getting rid of all the ~ characters.