[SOLVED] Newb having trouble with simple string substitution with sed
Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Newb having trouble with simple string substitution with sed
I've been trying to mess with sed for a simple string replacement issue:
change mysql_connect('localhost','user1','pass1');
to mysql_connect('localhost','user2','pass2');
sed: 1: "check.php": command c expects \ followed by text
which was right from the tutorial.
I also tried this script:
Code:
#!/bin/bash
mkdir onestopshop/backup
for f in onestopshop/*
do
cat "" > tmp.txt
cat $f | cat > $f.bkup
while read line
do
if [ -f $f ]
then
s=""
$s = sed 's/user1/user2/' $line | sed 's/pass1/pass2/'
if(("${#s}")>1)
then
cat $s >> tmp.txt
else
cat $line >> tmp.txt
fi
fi
done < $f
cp tmp.txt $f
done
exit 0
The sed command running on MacOS X is slightly different from the GNU-Linux version. The -i option requires an argument which will be used as suffix for a backup copy of the original file. Therefore the 's/user1/user2/g' part is somewhat considered the argument of option -i and check.php the sed command. To avoid that you can either let sed create a backup copy of the original file OR skip that using an empty string as argument, e.g.
You might also consider using ed instead. It's a true text editor, and can operate directly on the file.
Code:
printf '%s\n' 'g/localhost/s/user1/pass1/g' g/localhost/s/pass1/pass2/g' 'w' | ed check.php
In both sed and ed it generally helps efficiency and accuracy to filter the commands with address fields too, so that they only apply to the lines you want to change.
sed '/mysql_connect/s/user1/user2/g;s/pass1/pass2/g' check.php > tmpfile
mv tmpfile check.php
The "/mysql_connect/" part causes sed to only edit file that contain a matching string. This can prevent false positives.
The semicolon seperates two sed commands. Do that instead of piping on sed command to another. You can also use the -e argument for additional commands. Each command is run on a line before the next line is read.
I'm not familiar with bsd sed, so I didn't use the "-i" option.
I would't even dare messing with that script you posted. The "s" variable is unneccessary and looks wrongly used, It seems like it's hodpodged together from other scripts.
Thanks guys. The mac specific sed command worked like a charm. Now I'm working on the script for my debian server. Here's what I have:
Code:
#!/bin/bash
if [ ! -e backup ]
then
mkdir backup
fi
for f in *
do
if [[ $f -ne change && ! -d $f ]]
then
cp $f backup/$f
printf '%s\n' 'g/localhost/s/user1/pass1/g' 'g/localhost/s/pass1/pass2/g' 'w' | ed $f
printf '%s\n' 'g/localhost/s/user1/pass2/g' 'g/localhost/s/user1/user2/g' 'w' | ed $f
fi
done
exit 0
Which I'm debugging. Something tells me debian doesn't user bash. But I should be able to change that I think.
EDIT: replaced -ne with != and it got past line 8. Debian doesn't have ed, however.
I hate to double post but I like things to be separate. Whatever. My final solution, thanks to everyone who posted:
Code:
#!/bin/bash
if [ ! -e backup ]
then
mkdir backup
fi
for f in *
do
if [ "$f" != "change" ]
then
if [ ! -d $f ]
then
cp $f backup/$f
sed -i 's/user1/user2/g' $f
sed -i 's/pass1/pass2/g' $f
fi
fi
done
exit 0
sed '/mysql_connect/s/user1/user2/g;s/pass1/pass2/g' check.php > tmpfile
mv tmpfile check.php
The "/mysql_connect/" part causes sed to only edit file that contain a matching string. This can prevent false positives.
Small correction. The semicolon creates two independent expressions, so the address only limits the first substitution. The second one is still global.
You need to either duplicate the address in the second expression, or group the commands together with brackets.
Code:
sed '/mysql_connect/ { s/user1/user2/g ; s/pass1/pass2/g }' check.php > tmpfile
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.