32

I have a file with the following contents:

WORD1 WORD2 WORD3

How can I use sed to replace the string between WORD1 and WORD3 with foo, such that the contents of the file are changed to the following?:

WORD1 foo WORD3

I tried the following, but obviously I'm missing something because that does not produce the desired results:

sed -i '' 's/WORD1.*WORD3/foo/g' file.txt

Camden S.
  • 1,955
  • 1
  • 20
  • 26
  • Could there be something like `WORD1 foo WORD3 bar WORD1 baz WORD3` in your string (i. e. more than one match per string)? – Tim Pietzcker May 16 '12 at 07:18
  • Ah - good question, but no, it's not really necessary to accommodate for more than one match in this scenario. – Camden S. May 16 '12 at 12:49

3 Answers3

44
sed -i 's/WORD1.*WORD3/WORD1 foo WORD3/g' file.txt

or

sed -i 's/(WORD1).*(WORD3)/\1 foo \2/g' file.txt

You might need to escape round brackets, depends on your sed variant.

A.H.
  • 61,009
  • 14
  • 85
  • 115
vyegorov
  • 20,303
  • 6
  • 57
  • 72
7

This might work for you:

sed 's/\S\+/foo/2' file

or perhaps:

sed 's/[^[:space:]][^[:space:]]*/foo/2' file

If WORD1 and WORD3 occur more than once:

echo "WORD1 WORD2 WORD3 BLA BLA WORD1 WORD4 WORD3" |
sed 's/WORD3/\n&/g;s/\(WORD1\)[^\n]*\n/\1 foo /g'
WORD1 foo WORD3 BLA BLA WORD1 foo WORD3
potong
  • 51,370
  • 6
  • 49
  • 80
  • `[^[:space:]][^[:space:]]*` can be replaced by `[^[:space:]]\+` (as you have used in your first example) in some versions of `sed`. The `/2` is a nice touch. +1 – Dennis Williamson May 17 '12 at 04:47
3

content of a sample file.txt

$ cat file.txt 
WORD1 WORD2 WORD3
WORD4 WORD5 WORD6
WORD7 WORD8 WORD9

(Correction by @DennisWilliamson in comment)
$ sed -e 's/\([^ ]\+\) \+\([^ ]\+\) \+\(.*\)/\1 foo \3/' file.txt

WORD1 foo WORD3
WORD4 foo WORD6
WORD7 foo WORD9

while awk is somehow simpler

$ awk -F' ' '{ print $1" foo "$3 }' file.txt

WORD1 foo WORD3
WORD4 foo WORD6
WORD7 foo WORD9
Community
  • 1
  • 1
Rony
  • 1,614
  • 11
  • 10
  • 1
    It's not necessary to escape any of the spaces. And `[^\ ]` means "any character other than space or backslash. I would suggest `\+` instead of `*` since, as is, your command could replace an empty line. Also `g` is unnecessary - as is the redirection. – Dennis Williamson May 17 '12 at 04:40
  • Now it won't work at all. You misunderstood what I meant. `sed -e 's/\([^ ]\+\) \+\([^ ]\+\) \+\(.*\)/\1 foo \3/' file.txt` – Dennis Williamson May 17 '12 at 11:22