Date: Wed, 12 Mar 2003 18:38:23 +0200 From: Giorgos Keramidas <keramida@ceid.upatras.gr> To: Kok Kok <cckok002000@yahoo.ca> Cc: freebsd-questions@FreeBSD.ORG Subject: Re: sed to replace the words Message-ID: <20030312163823.GC5097@gothmog.gr> In-Reply-To: <20030312061655.26510.qmail@web13305.mail.yahoo.com> References: <20030312061655.26510.qmail@web13305.mail.yahoo.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On 2003-03-12 01:16, Kok Kok <cckok002000@yahoo.ca> wrote: > Hi all > > I have question how to replace words using sed > > ./script 61.100 192.168 > > The script is > > #!/bin/sh > sed -e 's/$2/$1/g' file > newfile > > The problem is 192.168 can't replace 61.100 in the > newfile . The sed utility won't see the value of $1 or $2 in this script, since you used simple quotes, which inhibit shell variable substitution. . The order of $1 and $2 is reversed. . Even if you swap $1 and $2 and change ' to ", the results can be weird for patterns that include the '.' character since it's a special sed character that matches *any* character. You need to escape it with a backslash (\) before testing it on real files. . The name of 'newfile' is hardwired, which means you can't run the script to substitute "$1" to "$2" on many files. One example of doing this with a relatively easy way would be: 1 #!/bin/sh 2 3 if [ $# -lt 2 ]; then 4 echo "usage: `basename $0` p-before p-after [file ...]" >&2 5 exit 1 6 fi 7 8 p_before="$1" 9 p_after="$2" 10 11 shift && shift 12 for fname in "$@" ;do 13 echo "Filtering ${fname} ..." 14 15 # Escape '.' and '|' in $p_before to avoid matching too many 16 # things. 17 p_before=$(echo "${p_before}" | sed -e 's|\.|\\.|g' -e 's,|,\\|,g') 18 19 # Filter, using a temp file. 20 tmpfile=$(mktemp ${TMPDIR:-/tmp}/sedXXXX 2>&1 || echo "") 21 if [ X"${tmpfile}" = X"" ]; then 22 echo "Can't create temp file." >&2 23 exit 1 24 fi 25 sed -e "s|${p_before}|${p_after}|g" "${fname}" > "${tmpfile}" 26 cat "${tmpfile}" > "${fname}" 27 /bin/rm -f "${tmpfile}" 28 done This script when run on a sample test I did seems to do what you asked, avoiding unnecessary matches: giorgos@gothmog[18:26]/home/giorgos$ cat koko This is a test line that should remain intact, despite having 150\.140 in it. The lines that include 150.140 should match and be changed. All other lines stay the same, since i.e. 150 140 doesn't match. giorgos@gothmog[18:26]/home/giorgos$ sh lala.sh 150.140 192.168 koko Filtering koko ... giorgos@gothmog[18:26]/home/giorgos$ cat koko This is a test line that should remain intact, despite having 150\.140 in it. The lines that include 192.168 should match and be changed. All other lines stay the same, since i.e. 150 140 doesn't match. There are quite a few tricks in that script which you probably don't need, but it does what you asked. Some sort of error checking for sed failures should be added, and you should probably check that it makes sense to overwrite the original file after sed is done, but well... that's another thing. - Giorgos To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-questions" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030312163823.GC5097>