0

I'm fairly new to Linux and recently started experimenting with the command line. I decided to make a file and called it 'hi.txt'. The contents of the document was:

This is hi.txt.
hi 
hi
hi

I used the command sed -i 's/hi/hotel/g' hi.txt in hopes of making all the 'hi's in the document change to hotel. This was the output:

Thotels is hotel.txt
hotel
hotel
hotel 

As you can see, the 'hi' is the word 'This' also got changed. Is there a way to stop this from happening?

2

The s/// command expects the "search" parameter to be a regular expression. Most versions of sed should support the \b match, which is a zero-width match at a word-nonword or a word-edge boundary. "Word" in this case is defined as a character that is either a letter, digit, or underscore (_). For example, if we assume the string c++ is on a line by itself in your file, \b would match at the following positions:

  1. Immediately before the c.
  2. Between the c and the first +.
  3. Immediately after the last +.

The following command should give you the desired results:

sed -i 's/\bhi\b/hotel/g' hi.txt

The word this will fail to match because the h is preceded by a word character (t), and the i is followed by a word character (s). However, the string This is hi.txt will match on the second instance of hi, because the surrounding space and . are both non-word characters.

| improve this answer | |
  • 1
    \b is a GNU extension to sed (probably borrowed from perl), which is not a problem here because the OP said he was running Linux (so he will have GNU sed by default). For proof of this, try running your sed script with --posix to disable all GNU extensions, and it will fail to change 'hi' to 'hotel' - without the GNU extensions it is searching for 'bhib' – cas Sep 20 '15 at 0:54
  • @cas Good point. An alternative would be to use \< and \>, which match the beginning and end of a word, respectively. While not POSIX nor completely portable, they are supported on FreeBSD and Solaris, as well as by BusyBox sed (though this page suggests they may be buggy on FreeBSD and BusyBox). In any event, OP can likely use \b on Linux, as you noted. – James Sneeringer Sep 21 '15 at 14:10
0
$ sed -e 's/\([^[:alnum:]_.-]\)hi\([^[:alnum:]_.-]\)/\1hotel\2/g' -e 's/^hi$/hotel/' <file
This is hi.txt.
hotel
hotel
hotel
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.