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>
