Input:
$ cat testing.list
deb [trusted=yes] http://10.47.4.220/repos/test-repo/11 /
$ echo $REPOVER
12
Expected output:
$ cat testing.list
deb [trusted=yes] http://10.47.4.220/repos/test-repo/12 /
Please note the change in the number at the end.
Attempt 1 with single quotes (Not working):
$ sed -r 's#(.*/)([[:digit:]]+)([[:space:]]+/)$#1$REPOVER3#' testing.list
deb [trusted=yes] http://10.47.4.220/repos/test-repo/$REPOVER /
Attempt 1.1 with single quotes without the variable (Working):
$ sed -r 's#(.*/)([[:digit:]]+)([[:space:]]+/)$#1123#' testing.list
deb [trusted=yes] http://10.47.4.220/repos/test-repo/12 /
Attempt 2 with double quotes (Not Working):
$ sed -r "s#(.*/)([[:digit:]]+)([[:space:]]+/)$#1$REPOVER3#" testing.list
sed: -e expression #1, char 44: unterminated `s' command
Attempt 2.1 with double quotes without the variable (Not Working):
$ sed -r "s#(.*/)([[:digit:]]+)([[:space:]]+/)$#1123#" testing.list
sed: -e expression #1, char 44: unterminated `s' command
So, it seems like sed
does not like double quotes
. However, Shell won’t expand variables unless I use double quotes
.
FWIW:
$ bash --version | head -1
GNU bash, version 5.0.3(1)-release (x86_64-pc-linux-gnu)
$ sed --version
sed (GNU sed) 4.7
Packaged by Debian
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
4
Answers
The
$#
is a variable in shell with number of arguments.So
$#
is replaced by0
(in case of my shell, it’s interactive, has no arguments).Research difference between single and double quotes. Research when to quote in shell. Research how quotation works in shell. You seem to want:
Your attempt 2 is almost correct. Just escape the
$
signs that you want to preserve from shell expansion:Another option is to use a mixture of simple quotes and double-quotes:
But all this works only if the value of your variable does not contain special characters that sed would interpret. If you have such characters you will need to first escape them. If, for instance, the value of
REPOVER
can contain#
,&
orcharacters you can:
A last, complicated one, in case
REPOVER
can really be anything, including endline characters, bash and sed special characters, etc. But let’s however assume it does not itself contain lines beginning withdeb
(if it did we would need a custom delimiter but the principle would be almost the same).We first print the variable, next cat the file, and pass all this to sed. The sed script first collects the preamble in the hold space, that is, everything until the first
^deb
line excluded. It then uses the content of the hold space for the replacement in all^deb
lines it encounters. Non^deb
lines after the preamble are printed unmodified:Demo:
Based on the sample data provided the proposed
sed
can be simplified a bit:Find and replace the pattern
/<at_least_one_number><space>
with/${REPOVER}<space>
Both of which produce:
Changing the delimiter and placing it in double quotes worked for me.