0

bash sed truncates file instead of replacing text.

I want to update variables in bashrc source with sed but to my surprise sed truncates the file.

For testing i have a little file abc:

export PATH=$PATH:$HOME/bin:$JAVA_HOME/bin
export myip=1.2.3.4

and this test script:

#!/bin/bash
myip=1.2.3.4; newip=5.6.7.8
sed -ni 's/$myip/$newip/' abc 

running the script leaves abc empty. Why is this so?

I am using Ubuntu 22.04 on an Intel I7.

user37342
  • 37
  • 3

2 Answers2

1

That is because of the quotes that you use, the -n option and the absence of a p behind the substitute.

In bash, the single quote ' makes sure that the text is taken literally, without variable expansion. So, you would probably want to use double quotes ".

Because yo use -n, you will probably want to print the line that you want to keep as well with the p:

sed -ni "s/$myip/$newip/p" abc

Note that, if you want to keep the lines that do not match, you just remove the -n.

Note too that the . in your myip pattern matches any character. So, your pattern 1.2.3.4 will match the 112.3.4 part of the IP address 112.3.4.9, which will then become 5.6.7.8.9.

Ljm Dullaart
  • 4,273
  • 2
  • 14
  • 31
  • Thanks, dropping the n option and using double quotes did the trick. – user37342 May 28 '23 at 11:21
  • 4
    @user37342 you have bigger problems than that - every `.` in `$myip` will be treated as a metachar matching every other char, and the whole thing wiill match as a substring so `"s/$myip/$newip/"` would convert any string like `foo1928374bar` to `foo5.6.7.8bar` anywhere in your input. See [is-it-possible-to-escape-regex-metacharacters-reliably-with-sed](https://stackoverflow.com/questions/29613304/is-it-possible-to-escape-regex-metacharacters-reliably-with-sed) and google word boundaries. – Ed Morton May 28 '23 at 11:35
0

There are two errors in your script.

  1. When you enclose a string into single quotes ', the substitution of the bash variables will not happen. You have to use double quotes ".

  2. If you use the -n option, you will produce no output except with the command p that you don't use.

The correct script is:

#!/bin/bash
myip=1.2.3.4; newip=5.6.7.8
sed -i "s/$myip/$newip/" abc 
Pierre François
  • 5,850
  • 1
  • 17
  • 38