LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This 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


Reply
  Search this Thread
Old 01-20-2013, 02:05 PM   #1
jddancks
LQ Newbie
 
Registered: Jan 2013
Location: Central NY
Distribution: Mac, debian
Posts: 29

Rep: Reputation: Disabled
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');

I was skimming this:

http://www.brunolinux.com/02-The_Ter..._with_Sed.html

I tried:

sed -i 's/user1/user2/g' check.php

I get:

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
 
Old 01-20-2013, 02:41 PM   #2
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
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.
Code:
sed -i '' 's/user1/user2/g' check.php
Hope this helps.
 
1 members found this post helpful.
Old 01-20-2013, 04:47 PM   #3
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
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.

How to use ed:
http://wiki.bash-hackers.org/howto/edit-ed
http://snap.nlc.dcccd.edu/learn/nlc/ed.html
(also read the info page)
 
1 members found this post helpful.
Old 01-20-2013, 05:05 PM   #4
jschiwal
LQ Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682
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.
 
1 members found this post helpful.
Old 01-21-2013, 02:11 PM   #5
jddancks
LQ Newbie
 
Registered: Jan 2013
Location: Central NY
Distribution: Mac, debian
Posts: 29

Original Poster
Rep: Reputation: Disabled
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.

Last edited by jddancks; 01-21-2013 at 06:32 PM.
 
Old 01-21-2013, 09:03 PM   #6
jddancks
LQ Newbie
 
Registered: Jan 2013
Location: Central NY
Distribution: Mac, debian
Posts: 29

Original Poster
Rep: Reputation: Disabled
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
 
Old 01-22-2013, 09:20 AM   #7
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Quote:
Originally Posted by jschiwal View Post
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
Now the address applies to both.


Here are a few useful sed references:
http://www.grymoire.com/Unix/Sed.html
http://sed.sourceforge.net/grabbag/
http://sed.sourceforge.net/sedfaq.html
http://sed.sourceforge.net/sed1line.txt


Edit: Oh, and I just remembered that it's possible to combine them in ed too, if you construct the 'g' (global) command correctly:

Code:
printf '%s\n' 'g/localhost/ s/user1/user2/g\' 's/pass1/pass2/g' 'w' | ed -s "$f"
You can have multiple expressions after the 'g', provided you add a backslash at the end of each one to indicate continuation.

Last edited by David the H.; 01-22-2013 at 09:33 AM. Reason: stated
 
  


Reply

Tags
bash, script, sed



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
string substitution lipun4u Programming 11 01-13-2011 01:47 AM
string substitution lipun4u Linux - Newbie 3 02-22-2010 02:19 AM
Help with a sed substitution string hawgwild Programming 2 09-24-2009 02:35 PM
Trouble with sed substitution and file output bezeek Programming 2 09-03-2009 03:45 AM
simple substitution with sed? ocicat Programming 9 02-22-2008 11:45 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 03:16 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration