Replacing a part of a line with bash / perl - perl

I'm a noob at bash need to replace the mypassword part of this line in a file
"rpc-password": mypassword
with mynewpassword
I tried
perl -pi -e "s,PASSWORD,${password},g" "${user_conf}"
but it dosen't seem to do anything :(
I can use anything that will work inside a bash script, it dosen't have to be bash or perl.

perl -pi -e 's/mypassword/mynewpassword/g' file
will work

Using a loose regex without keeping backups is a bad idea. Especially if you intend to use dynamic replacement strings. While it may work just fine for something like "mypassword", it will break if someone tries to replace with the password "ass" with "butt":
"rpc-password": mypassword
Would become:
"rpc-pbuttword": butt
The more automation you seek, the more strict you need the regex to be, IMO.
I would anchor the replacement part to the particular configuration line that you seek:
s/^\s*"rpc-password":\s*\K\Q$mypassword\E\s*$/$mynewpassword/
No /g modifier, unless you intend to replace a password several times on the same line. \K will preserve the characters before it. Using \s* liberally will be a safeguard against user-edited configuration files where extra whitespace might have been added.
Also, importantly, you need to quote meta characters in the password. Otherwise a password such as t(foo)? Will also match a single t. In general, it will cause strange mismatches. This is why I added \Q...\E (see perldoc perlre) to the regex, which will allow variable interpolation, but escape meta characters.

You can also use sed for this:
sed -i 's/mypassword/mynewpassword/g' file

Related

backslashes in perl substitution

I'm trying my luck with a perl one-liner changing some commands in a bunch of .tex files. I got as far as the following:
perl -pi -e "s/\Q\linenum{some more stuff}\E/\Q\uln\E/g" *tex
Which results in \lLn instead of the expected replacement patter \uln. Apparently while \Q and \E take care of other special characters, they don't take care of the \l \u changing the case of the next character, how would I do that?
\Q\E works best for \Q$var\E. Elsewhere, you can use \ to escape characters that need escaping.
perl -i -pe's/\\linenum\{some more stuff\}/\\uln/g' *tex

What is the purpose of filtering a log file using this Perl one-liner before displaying it in the terminal?

I came across this script which was not written by me, but because of an issue I need to know what it does.
What is the purpose of filtering the log file using this Perl one-liner?
cat log.txt | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)/ /g'
The log.txt file contains the output of a series of commands. I do not understand what is being filtered here, and why it might be useful.
It looks like the code should remove ANSI escape codes from the input, i.e codes to set colors, window title .... Since some of these code might cause harm it might be a security measure in case some kind of attack was able to include such escape codes into the log file. Since usually a log file does not contain any such escape codes this would also explain why you don't see any effect of this statement for normal log files.
For more information about this kind of attack see A Blast From the Past: Executing Code in Terminal Emulators via Escape Sequences.
BTW, while your question looks bad on the first view it is actually not. But you might try to improve questions by at least formatting it properly. Otherwise you risk that this questions gets down-voted fast.
First, the command line suffers from a useless use of cat. perl is fully capable of reading from a file name on the command line.
So,
$ perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)/ /g' log.txt
would have done the same thing, but avoided spawning an extra process.
Now, -e is followed by a script for perl to execute. In this case, we have a single global substitution.
\e in a Perl regex pattern corresponds to the escape character, x1b.
The pattern following \e looks like the author wants to match ANSI escape sequences.
The -p option essentially wraps the script specified with -e in while loop, so the s/// is executed for each line of the input.
The pattern probably does the job for this simple purpose, but one might benefit from using Regexp::Common::ANSIescape as in:
$ perl -MRegexp::Common::ANSIescape=ANSIescape,no_defaults -pe 's/$RE{ANSIescape}/ /g' log.txt
Of course, if one uses a script like this very often, one might want to either use an alias, or even write a very short script that does this, as in:
#!/usr/bin/env perl
use strict;
use Regexp::Common 'ANSIescape', 'no_defaults';
while (<>) {
s/$RE{ANSIescape}/ /g;
print;
}

How to get sed to include a double \\ that's included in a variable

I'm writing a script in bash that performs a simple transform of a file we'll call storage.config.
Parameters are passed from our automation system (VCAC\AppD) to our action script, which performs the transform using sed.
To keep things simple, I'll use the following example
storage.config - To be transformed
url=jdbc:sqlserver://#myDB
Transform Script
myDB='serverxyz\\instance'
sed -i -e "s,#myDB,$myDB,g" storage.config
I would expect the resulting storage.config to look like this;
url=jdbc:sqlserver://serverxyz\\instance
However, it looks like this instead;
url=jdbc:sqlserver://serverxyz\instance
I've read through the answers on this site, as well as others. And have found a lot of useful information on how to include variable, single vs. double quotes, but nothing on how to retain a double \ in a variable. I'd like to get sed to interpret correctly, rather than type something like;
myDB='serverxyz\\\\instance'
This value will be entered by Solutions Engineers, who might enter improperly as they don't recognize it as a valid SQL instance.
sed is interpreting it correctly.
You are sticking \\ in the replacement as a literal string.
sed doesn't know it was a variable from somewhere else and not just typed out manually.
Escaping it is the answer.
You can do it at expansion time with ${myDB//\\/\\\\} if you want though.
Additionally, as #abesto quite correctly indicated in his answer, you are loosing the doubled slash before sed even sees it. Use single quotes in your assignment to preserve it.
myDB='server\\instance'
The double \ doesn't even get as far as sed. Your shell sees \\, and reads it as "oh, you want a \, because you escaped it". You can try it out like this:
myDB="serverxyz\\instance"
echo "$myDB"
# output: serverxyz\instance
So in conclusion (Thanks to all that responded. Special thanks to #Etan);
myDB='serverxyz\\instance'
sed -i -e "s,#myDB,${myDB//\\/\\\\},g" storage.config
The above code results in the proper translation\transform of my storage.config file. The resulting storage.config is as follows;
url=jdbc:sqlserver://serverxyz\\instance

Perl Search and replace keeping middle part of string

I've been using Codeigniter for my PHP project and I've been using their session class.
$this->session->userdata('variablename')
I've been having a lot of problems with this so i've decided to use PHP Native session.
$_SESSION['variablename']
This is what I've got so far
perl -p -i -e "s/$this->session->userdata('.*?$SOMEVAR.*?\')/$_SESSION['$1']/g" offer.php
But truth to be told I don't really know what I'm doing.
I would also like to do this on all php files in my project.
Help much appreciated.
The regex should be:
s/\$this->session->userdata\('(.?)'\)/$_SESSION['$1']/g
Issues with the version you posted are mostly with un-escaped characters--you can escape a $ or parenthesis by adding a \ prior to the character. For example, \$this will find the text "$this", while $this will search for the value of the $this variable.
For a more comprehensive look at escapes (and other quick tips), if you have $2, I highly recommend this cheat sheet.
Also, you don't need to use the .*?$SOMEVAR.*? construct you added in there...Perl will automatically capture the result found between the first pair of parentheses and store it in $1, the second set of parentheses gets $2, etc.
When shell quoting is getting complicated, the simplest thing to do is to just put the source into a file. You can still use it as a one-liner. I have used a negative lookahead assertion to make sure that it does not break for escaped single quotes inside the string.
# source file, regex.txt
s/\$this->session->userdata\('(.+?)(?!\\')'\)/\$_SESSION['$1']/g;
Usage:
perl -pi regex.txt yourfile.php
Note that you simply leave out the -e switch. Also note that -i requires a backup extension for Windows, e.g. -i.bak.

sed in perl script

I am using following kind of script in my perl script and expecting entry at line 1. I am getting some error as below; any help?
plz ignore perl variable....
Error Messaage -
sed: -e expression #1, char 22: extra characters after command
# Empty file will not work for Sed line number 1
`"Security Concerns Report" > $outputFile`;
`sed '1i\
\
DATE :- $CDate \
Utility accounts with super access:- $LNumOfSupUserUtil \
Users not found in LDAP with super access: - $LNumOfSupUserNonLdap\
' $outputFile > $$`;
`mv $$ $outputFile`;
}
Your immediate problem is that the backslash character is interpreted by Perl inside the backtick operator, as is the dollar character. So your backslash-newline sequence turns into a newline in the shell command that is executed. If you replace these backslashes by \\, you'll go over this hurdle, but you'll still have a very brittle program.
Perl is calling a shell which calls sed. This requires an extra level of quoting for the shell which you are not performing. If your file names and data contain no special characters, you may be able to get away with this, until someone uses a date format containing a ' (among many things that would break your code).
Rather than fix this, it is a lot simpler to do everything in Perl. Everything sed and shells can do, Perl can do almost as easily or easier. It's not very clear from your question what you're trying to do. I'll focus on the sed call, but this may not be the best way to write your program.
If you really need to prepend some text to an existing file, there's a widely-used module on CPAN that already does this well. Use existing libraries in preference to reinventing the wheel. File::Slurp has a prepend_file method just for that. In the code below I use a here-document operator for the multiline string.
use File::Slurp; # at the top of the script with the other use directives
File::Slurp->prepend_file($outputFile, <<EOF);
DATE :- $CDate
Utility accounts with super access:- $LNumOfSupUserUtil
Users not found in LDAP with super access: - $LNumOfSupUserNonLdap
EOF