6

I have the following block of text in a file:

test3.legacy test4.legacy test3 test3.kami

I only want to search for test3 as a whole and replace it with nothing. Unfortunately, all my attempts have removed test3 from test3.legacy and test3.kami. I've tried:

sed 's/^test3://g' myfile.txt
sed 's/\btest3\b//g' myfile.txt
sed 's/\<test3\>//g' myfile.txt

without any luck. Any ideas how I can resolve this please?

EDIT: Most attempts have resulted in the following: .legacy test4.legacy .kami

5 Answers 5

6

Is this what you want?

$ sed 's/\(^\| \)test3\( \|$\)/\1/g' file
test3.legacy test4.legacy test3.kami

This say

substitute
   (^ start of line OR space)
   test3
   (space OR end of line)
with match 1 (AKA space or start of line)

Update:

And as so elegantly put by the good @Stephane Chazelas this would not take care of certain cases. Also emphasize on the portability part. See answer below.

A GNU variant could, (hopefully), be:

sed 's/\(^\| \)\(test3\( \|$\)\)*/\1/g'
# Or perhaps:
sed 's/\(^\| \)\(test3\( \|$\)\)\+/\1/g'

taking care of repetitive matches. Optionally one would take care of multiple spaces etc as well. Depending on input.

EOUPD


As an alternative perhaps (only meant as a starting point):

sed 's/\Wtest3\W/ /g'

Not this I assume:

$ sed 's/test3\.\?[^ ]* *//g' file
test4.legacy
8
  • Sukminder, the first command was perfect! Thank you! Would you mind explaining the reason for the pipes (|)?
    – maGz
    Commented May 5, 2013 at 19:31
  • It is not perfect as to if start or end of line. Correcting.
    – Runium
    Commented May 5, 2013 at 19:36
  • Now you're just showing off 8-)
    – slm
    Commented May 5, 2013 at 19:37
  • 1
    Note that none of \|, \W or \? are standard sed. So the above will work with GNU sed, but probably not many others. Commented May 5, 2013 at 19:54
  • 1
    The first one would fail to remove the second test3 in test3 test3. The second would turn x.test3.y into x y. Commented May 5, 2013 at 20:12
3

I'd look for test3 wrapped with a space on either side, \s, given your example rather than try and use the word boundary notation.

For example

$ echo "test3.legacy test4.legacy test3 test3.kami" | sed 's/\stest3\s/ /g'
test3.legacy test4.legacy test3.kami

The above looks for space test3 space and replaces this with just a space.

NOTE: This won't handle the situation where test3 is first in the list!

5
  • Hi slm, Thank you for the response. Your solution makes sense and also works.
    – maGz
    Commented May 5, 2013 at 19:37
  • Yup, @Sukminder was a little quicker hitting the submit button, thanks for the question 8-).
    – slm
    Commented May 5, 2013 at 19:38
  • 1
    Note that \s is a GNU extension (inspired by perl) and is short for the standard [[:space:]], not [[:blank:]], that is it includes all the horizontal and vertical spacing characters, not just tab and space. It is also locale dependant. Your solution would also fail to remove the second test3 in "x test3 test3 y" Commented May 5, 2013 at 20:07
  • @StephaneChazelas, thanks for the improvement. Question, is it better to adjust our answers in situations like this or leave them and let the comments pick up these nuances? You've corrected a couple of my answers, which I appreciate, since I'm learning like everyone else, but I wasn't sure what was the correct thing to do?
    – slm
    Commented May 5, 2013 at 20:14
  • Up to you really. I'm not sure there's some consensus on that. You can always ask on meta. Nothing wrong in editing the answer to improve or point out the limitations even if you come to realise that through others' comments IMO. Commented May 5, 2013 at 20:27
3

Portably:

sed -e 's/.*/ & /' -e :1 -e 's/ test3 / /g;t1' -e 's/^ //;s/ $//'

That is:

  • first add a space at the beginning and end of the line, to not have to consider test3 at the beginning and end specially,
  • replace test3 enclosed in spaces with a single space,
  • repeat the process as long as there are substitutions (to cover the test3 test3 cases).
  • Remove the leading and trailing space that we added initially.
-1

This also worked for me by just removing the word test3

sed 's/ test3 .//g' 
1
  • This is not going to delete the first t from test3.kami from the block of text as well
    – Anthon
    Commented Mar 15, 2015 at 13:43
-1
sed -e 's/ test3 / /g' -e 's/ test3//g' -e 's/test3 //g' myfile.txt

Please try above

1
  • A script is not enough without a textual elaboration.
    – peterh
    Commented Jul 9, 2015 at 0:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .