Thanks to all who replied and tried to help, i learnt alot from everyone. Wyatt ================ ORIGINAL PROBLEM ================ 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 foofoo foofoo foo foo foo foo foo foo foo foo foo more foo -------------- ================ SOLUTION ================ /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' -------------- #!/usr/bin/perl open(f,"./file"); while(<f>) { $_=~ s,(\s+)foo(\s+),$1bar$2,g; $_=~ s,(\s+)foo(\s+),$1bar$2,g; $_ =~ s,^foo(\s+),bar$1$`,; print; } -------------- 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++' 1,$s/\<foo\>/bar/g w q ++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/ 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