SUMMARY: SED problem

From: Wyatt Song <>
Date: Tue Oct 23 2001 - 23:26:42 EDT
Thanks to all who replied and tried to help, i learnt alot from everyone.


I'd like all "foo" that preceeds or followed by any number of spaces and/or
tabs be changed, words like foofoofoo should remain the same.  (hopefully
i'm making enough sense)

The file contents are:
	 	foo	 foooo	tab space	 foofoo	foo	   	
foo 	 foo 
foofoo	foo		foo  space tab
	foo	 foo 	
	foo	   foo 
   foo	  foo
     foo    foo more		foo

/usr/bin/sed 's/\<foo\>/bar/g'

Ray Brownrigg pointed out /usr/ucb/sed will not work. Sanjiv Bhatia
recommanded using POSIX version /usr/xpg4/bin/sed, Oreilly book mentioned \<
and \> belong to the extended regular expressions set which matches the
empty string at the beginning and the end of a word.

James Ashton also pointed out the wording in my original posting which leads
to a slight ambiguity, I should have specified that a foo must be preceeded
_AND_ followed by whitespace (or tabs).

Other Good Ideas
Many people approached this problem using the standard regex matching
approach, the tricky part i guess is the [^] and [$] also affect how we
match the words.  I was also recommanded to use Pearl, given ed solutions,
change Tab to Space using expand before pipe into sed, etc.  Thanks.  I
listed most of the recommandations for those interested.

the possible combinations are

space foo space
space foo tab
space foo newline
tab foo space
tab foo tab
tab foo newline
newline foo space
newline foo tab
newline foo newline

sed -e 's/_foo_/_bar_/g' -e 's/_foo-/_bar-/g' -e 's/_foo$/_bar/' \
sed -e 's/-foo_/_bar_/g' -e 's/-foo-/_bar-/g' -e 's/-foo$/_bar/' \
sed -e 's/^foo_/bar_/' -e 's/^foo-/bar-/' -e 's/^foo$/bar/' filename
sed 's/[	 ][	 ]*foo[	 ][	 ]*/ bar /g'
sed 's/\([	 ][	 ]*\)foo\([	 ][	 ]*\)/\1bar\2/g'
sed 's/\([   ]\)foo\([   ]\)/\1bar\2/g'
   $_=~ s,(\s+)foo(\s+),$1bar$2,g;
   $_=~ s,(\s+)foo(\s+),$1bar$2,g;
   $_ =~ s,^foo(\s+),bar$1$`,;
cat test | perl -pe '$_ =~ s/foo/bar/g && print'
cat test | expand | sed 's/  *foo  */ bar /g'
sed 	-e 's/\([ 	]\)foo\([ 	]\)/\1bar\2/ \
	-e 's/^foo\([ 	]\)/bar\1/ \
	-e 's/\([ 	]\)foo$/\1bar/ 
 ed -s testfile << '++GOOF++'
sed -e 's/\([<sp-tab]\)foo\([<sp-tab>]\)/\1bar\2/g' \
   -e 's/^foo\([<sp-tab>]\)/bar\1/'  \
   -e 's/\([<sp-tab>]\)foo$/\1bar/'  test
#!/bin/sh -

# The problem is that sed has some pretty primitive regular expressions,
# so we have to handle 4 cases:
#   ^fooWS
#   ^foo$
#   WSfoo$
#   WSfooWS
#   Also, there is no 'look ahead' regular expressions so we can't just use
# 's/WSfooWS/bar/g' because that wouldn't match 'WSfooWSfooWS', because the
# middle WS gets consumed by the first match.  To work around this I use
# a loop.
cat foo.test \
  | sed \
	-e ':lahead' \
	-e 's/\([ 	][ 	]*\)foo\([ 	][ 	]*\)/\1bar\2/' \
	-e 't lahead' \
  	-e 's/^foo\([ 	][ 	]*\)/bar\1/' \
        -e 's/^foo$/bar/' \
	-e 's/\([ 	][ 	]*\)foo$/\1bar/'
sed -e 's/\([ 	]*\)foo\([ 	]\)/\1bar\2/g'
(note [] contains a space and a tab above)
seems to work. Or:
perl -e 's/(\s+)foo(\s+)/$1bar$2/g'
sed -f sedf test where the contents of sedf are:

s/ foo / bar /g
s/      foo     /       bar     /g
s/ foo  / bar   /g
s/      foo /   bar /g
s/^foo /bar /g
s/^foo  /bar    /g
s/ foo$/ bar/
s/      foo$/   bar/
perl -pe 's/\bfoo\b/bar/g'
sed -e "1,$s/ foo / bar /g"  filename > newfile
# sed 's:\([    ]*\)foo\([      ]*\):\1bar\2:g
s:\([   ]*\)foo\([      ]*\):\1bar\2:g
s:^foo\([       ]*\):bar\1:
s:\([   ]*\)foo$:\1bar:' test
sed 's/\([^a-zA-Z][^a-zA-Z]*\)foo\([^a-zA-Z][^a-zA-Z]*\)/\1bar\2/g' | \
sed 's/^foo\([^a-zA-Z][^a-zA-Z]*\)/bar\1/' | \
sed 's/\([^a-zA-Z][^a-zA-Z]*\)foo$/\1bar/' | \
sed 's/^foo$/bar/'
sed 's/\([ |   ]\)foo\([ |     ]\)/\1bar\2/g'
Received on Wed Oct 24 04:26:42 2001

This archive was generated by hypermail 2.1.8 : Wed Mar 23 2016 - 16:32:34 EDT