Search for bash for loop syntax using perl command - perl

I have several bash scripts that need to be modified and I would very much prefer to not do it by hand... basically, they all contain the line
for ((i=${BEGIN} ; i < ${END} ; i++))
and I need to change this to
for ((i=${BEGIN}-1 ; i < ${END} ; i++))
the i=${BEGIN} is unique and appears only once in each file, so I figured I could search and replace it using a simple perl command. What I came up with is
> perl -w -i -p -e "s/i=\$\{BEGIN\}/i=\$\{BEGIN\}-1/" Script.sh
which results in the following error
syntax error at -e line 1, near "{BEGIN"
syntax error at -e line 1, near "}continue"
Execution of -e aborted due to compilation errors.
What is the syntax error here?
Thanks!
Tsadkiel

Use apostrophes instead of double quotes:
perl -w -i -p -e 's/i=\$\{BEGIN\}/i=\$\{BEGIN\}-1/'
This way, backslashes aren't removed by shell, so perl sees them and they escape what they should escape.

The bash shell is performing interpolation on the argument "s/i=\$\{BEGIN\}/i=\$\{BEGIN\}-1/" before it gets to Perl. Let's see how that might work:
$ echo "s/i=\$\{BEGIN\}/i=\$\{BEGIN\}-1/"
s/i=$\{BEGIN\}/i=$\{BEGIN\}-1/
The substitution s/i=$\{BEGIN\}/i=$\{BEGIN\}-1/ is going to be a problem in Perl because Perl will treat the sequence $\{ as the start of a lookup on the hash variable %\, but it will fail to compile because it won't find an (unescaped) closing brace. So what you really want Perl to see is something like
s/i=\$\{BEGIN\}/i=\$\{BEGIN\}-1/
And there are at least two ways to change your original command-line to accomplish this:
Escape the dollar signs:
perl -wpi -e "s/i=\\\$\{BEGIN\}/i=\\\$\{BEGIN\}-1/"
Prefer single quotes, which aren't interpolated in bash:
perl -wpi -e 's/i=\$\{BEGIN\}/i=\$\{BEGIN\}-1/'

Related

Perl Search and Replace Command Not Working When Called from Inside another Perl Script

I am a beginner with Perl. I am using the Below Perl Command To Search and Replace "/$" Sequence in my tcl Script. This works well When used on the linux Command Line directly.
perl -p -i -e 's/\/\$/\/\\\$/g' sed_list.tcl
I am calling to Call the above Perl One liner in another Perl script using System Command and only with " ` " Back Tick.
system(`perl -p -i -e 's/\/\$/\/\\\$/g' sed_list.tcl`);
`perl -p -i -e 's/\/\$/\/\\\$/g' sed_list.tcl`;
I am getting the Below error. Please Help With this issue.
Bareword found where operator expected at -e line 1, near "$/g"
(Missing operator before g?)
Final $ should be \$ or $name at -e line 1, within string
syntax error at -e line 1, near "s//$/"
Execution of -e aborted due to compilation errors.
I Dont Know if I Can use any other Separation Operator like % and # just like SED command but, When I used '%' operator for separation, I didn't see error but job is not done.
`perl -p -i -e 's%\/\$%\/\\\$%g' sed_list.tcl`;
I couldn't find sufficient results for this particular issue of '$' variable on the web. Any help is appreciated.
Some one here Suggested that I should Escape all Back Slashes while using System Command or calling another command using BackTicks from inside a perl script. But later they have deleted their answer. It worked for me. I would like to thank every one for taking effort and helping me out in solving my question.
Here is the correct working code.
`perl -p -i -e 's/\\\/\\\$/\\\/\\\\\\\$/g' sed_list_gen.tcl`;
or Use System function as shown Below
system("perl -p -i -e 's/\\\/\\\$/\\\/\\\\\\\$/g' sed_list_gen.tcl");
Thanks once again for the community for helping me out. . .
You can execute an external command by passing the command to a system function or by using backticks(``) operator. Please pass the command to the system() function as a string:
system(q{perl -p -i -e 's/\/\$/\/\\\$/g' sed_list.tcl})
or use backticks as:
`perl -p -i -e 's/\/\$/\/\\\$/g' sed_list_gen.tcl`
Edit:
As suggested by Paul in the comments.

perl find and replace from command line. special characters?

So, I have looked around for an answer to this, and indeed I have found some, but none seem to work...
I have a folder full of bash scripts that I need to modify. specifically, I need to replace the line
INPUT=/data/scratch02/mpgussert/HAWC-30/${RUN}_reco
with
INPUT=/data/hawc01/hawcroot/data/hawc/reconstructed/quesadilla/${RUN}
I have tried this
perl -w -i -p -e "s'INPUT=/data/scratch02/mpgussert/HAWC-30/${RUN}_reco'INPUT=/data/hawc01/hawcroot/data/hawc/reconstructed/quesadilla/${RUN}'g" *.sh
which executes without error, but does not find and replace the desired text. From my understanding, using ' to deliminate the regex should search without special character replacement. Is that correct? If so, any ideas why it fails?
I have also tried
perl -w -i -p -e "s/INPUT=\/data\/scratch02\/mpgussert\/HAWC-30\/\$\{RUN\}_reco/INPUT=\/data\/hawc01\/hawcroot\/data\/hawc\/reconstructed\/quesadilla\/\$\{RUN\}/g" *.sh
the backslash should ignore special character replacement, but this returns the following error.
Backslash found where operator expected at -e line 1, near "RUN\"
syntax error at -e line 1, near "RUN\"
Execution of -e aborted due to compilation errors.
So it's searching for RUN\, which is not what I want... Any thoughts? I would appreciate any help you can give.
Thanks!
You want the pattern to be ...\$\{RUN\}..., but that's not what you're passing:
$ echo "...\$\{RUN\}..."
...$\{RUN\}...
You either need do more escaping, or switch to single quotes.
$ echo '...\$\{RUN\}...'
...\$\{RUN\}...
All together:
perl -i -wpe'
s{INPUT=/data/scratch02/mpgussert/HAWC-30/\$\{RUN\}_reco}
{INPUT=/data/hawc01/hawcroot/data/hawc/reconstructed/quesadilla/\${RUN}}g
' *.sh

Perl one-liner to remove trailing space from a file

I am calling a perl one-liner inside a Perl script.
The intention of the one-liner is to remove the trailing space from a file.
Inside the main perl script:
`perl -pi -e 's/\s+$//' tape.txt`;
Now it is throwing me an error Substitution replacement not terminated at -e line 2.
Where is it going wrong?
It's because of the $/ (special variable) inside your main perl script. Note that variables are interpolated inside `` strings just like inside "" strings, and the fact that there are some single quotes in there doesn't change that. You need to escape that $:
`perl -pi -e 's/\s+\$//' tape.txt;`
The backtick syntax invokes a shell and when invoked, the shell assumes it should interpolate the string passed.
A cleaner syntax might be:
system('perl -pli -e "s/\s*$//" tape.txt');
Since you aren't capturing the output of the command, using backticks or qx in lieu of system isn't an issue.
Too, adding the -l switch autochomps each line read and then adds a newline back --- probably what you want.
\s matches [ \t\n\r\f] and do not want to match \n.
Notice use of {} for subst delimiters:
$ echo -e 'hi \nbye'| perl -pe 's{[\t\040]+$}{};' | cat -A
hi$
bye$

Syntax Error Bareword found running Perl from Ubuntu Shell using variables containing forward slashes

I'm using Ubuntu Natty.
I'm trying to edit a text file using command-line perl. Below is a snippet of my code:
path_to_php_exec="/usr/local/php/bin/php"
path_to_php_prog="/root/run/php_gearman_worker.php"
perl -0777 -i -pe "s/(command[ ]*=[ ]*)[^\n]+/\${1}=$path_to_php_exec $path_to_php_prog\n/g" /etc/supervisord_program_gearman.conf
However, when I run this I get the following error
Bareword found where operator expected at -e line 1, near "s/(command[ ]*=[ ]*)[^\n]+/${1}=/usr"
Backslash found where operator expected at -e line 1, near "php\"
syntax error at -e line 1, near "s/(command[ ]*=[ ]*)[^\n]+/${1}=/usr"
Execution of -e aborted due to compilation errors.
I have a feeling it has something to do with the forward slashes in my shell variables but I'm not quite sure. Still somewhat of a newbie with command line scripting.
I would appreciate some assistance.
Thanks.
Yes, that's exactly it. You can choose different delimiters for Perl's s/// command. Also, your regex is line oriented, so why not parse the file line-by-line?
perl -i -pe \
"$(printf 's{(command\s*=\s*).*}{$1 %s %s}g' "$path_to_php_exec" "$path_to_php_prog")" \
/etc/supervisord_program_gearman.conf
I assume you don't want to double the equal sign in the output file, so I removed it from the substitution block.

Using perl in windows oddities

I've got windows bat file, (using activeperl)
#echo off
perl -p -e 's/DIV\[/div\[/g' orginal.txt > output.txt
perl -p -e 'rename("output.txt", "orginal.txt")';
...
Running a .bat file, and I just cant get it to run properly..
Can't open ;: No such file or directory, <> line 12248.
Can't find string terminator "'" anywhere before EOF at -e line 1.
Not sure what I'm doing wrong..
You can't use single-quotes to enclose the Perl code in Windows. As a result, you need to escape the double-quotes or find other alternatives, such as qq(...).
perl -pe "s/DIV\[/div\[/g" original.txt > output.txt
perl -pe "rename(qq(output.txt), qq/original.txt/)"
Note that in this case, the arguments to rename can simply be rename('a.txt', 'b.txt') since they are literals and no variable interpolation is required.
You ought to use double quotes to quote the program text under Windows cmd. In your example, you can just swiztch double and single quotes. In cases where you really need double quotes in the perl text, use qq{ .... } instead.
The other posters are correct: windows requires double quotes for -e scripts to perl, which often screws things up. There is one more thing you can do, though: Use the -i switch, like this:
#echo off
perl -pi.bak -we "s/DIV\[/div\[/g" original.txt
The -i.bak switch will edit the file in place - no rename required - AND it will store a backup of the file in "original.txt.bak". If you do not want a backup, remove the ".bak" part and just use -pi.