This question already has answers here:
Escape a string for a sed replace pattern
(17 answers)
Closed 9 years ago.
I have a sed command in a bash script like this:
sed -i 's/db.url=.*/db.url='$URL'/' config.properties
and URL var is assigned as:
$URL=jdbc\:oracle\:thin\:#\/\/hostname\:12345\/XYZ
When I run this bash script on the host it exists on it work as intended, replacing the url with the one specified in URL. However, when I add a command in the bash script to do this on my other host like this:
ssh user#host02 <<EOF
sed -i 's/db.url=.*/db.url='$URL'/' config.properties
exit
EOF
I get this error:
sed: -e expression #1, char 47: unknown option to `s'
Anyone know what may be going on here?
You've properly quote the sed expression if it were running on the local host, but the string is then passed to the shell on the remote host, where the * is now unquoted and expanded as a glob. The simplest thing to do is to pipe the command to the remote shell via standard input, so you don't have to worry about quoting:
echo "sed -i 's/db.url=.*/db.url=$URL/' config.properties" | ssh user#host02 bash
With multiple commands, you may consider using a here document:
ssh user#host02 bash <<EOF
command1
sed -i 's/db.url=.*/db.url=$URL/' config.properities
command2
EOF
The solution was to use double single quotes (') around $URL like this: ''$URL''
Related
This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 2 years ago.
I have a requirement where I need to replace line feed characters appearing as part of a data field in a CSV files. Fortunately all the unnecessary linefeeds are followed by an '_' character. So I decided to used sed to preprocess the file. The following command in sed works if run it interactively.
sed -i -e ':a;N;$!ba;s/\n_/_/g' file
But in server, the command will get executed with sh -c "<command>"
To test it in local, I ran the same command with sh and it is not working. The command looks as follows.
sh -c "sed -i -e ':a;N;$!ba;s/\n_/_/g' file"
Not sure what I'm missing. Please help.
Between double-quotes, $! expands to the PID of most recent background command (or the empty string if there is not one). Pass sed script as a positional parameter to sh to avoid dealing with quotation issues/escaping every special character:
sh -c 'sed -i -e "$1" file' _ ':a;N;$!ba;s/\n_/_/g'
See also: Difference between single and double quotes in Bash
I am trying to add an argument to the flag batch start. This is the error it gives me. Any idea on how to fix this?
$ sed -i "s/batch_start.*/batch_start\ 1111/" /tmp/runfile
sed: -e expression #1, char 27: unterminated `s' command
The root problem is that the command is being sent over ssh; that means it's running through two levels of shell parsing, one on the local computer, then another on the remote computer. That means it goes through quote/escape parsing, application, and removal twice, so you need two "layers" of quoting/escaping.
The command in the last comment doesn't parse (mismatched quotes), but I can reproduce the error message with this command:
ssh remoteHost "sudo sed -i "s/batch_start.*/batch_start\ 1111/" /tmp/runfile"
This sort-of has two levels of quotes, but quotes don't nest, so it doesn't work. The local shell parses this as a double-quoted string "sudo sed -i ", then an unquoted section s/batch_start.*/batch_start\ 1111/ (which contains an escaped space, so it'll remove the escape), then another double-quoted section: " /tmp/runfile". Since there are no spaces between them, they all get passed to ssh as a single argument. You can see the post-parsing string by replacing ssh remoteHost with echo:
$ echo "sudo sed -i "s/batch_start.*/batch_start\ 1111/" /tmp/runfile"
sudo sed -i s/batch_start.*/batch_start 1111/ /tmp/runfile
...so that's the command the remote shell will execute. Since there's a space between s/batch_start.*/batch_start and 1111/, they get passed to sed as separate arguments, and it treats the first as the command to execute (which is missing a close /) and the second as a filename.
Solution: there are many ways to correct the quoting. You can use the echo trick to see what'll get sent to the remote shell. I tend to prefer single-quotes around the entire command, and then just quote normally inside that (as long as the inner command doesn't itself contain single-quotes). In this case, that means:
ssh remoteHost 'sudo sed -i "s/batch_start.*/batch_start 1111/" /tmp/runfile'
which executes this on the remote computer:
sudo sed -i "s/batch_start.*/batch_start 1111/" /tmp/runfile
(note that I removed the escape on the space.)
I am trying to add a user "demouser" to /etc/sudoers of a remote server and I want to pass the username from a variable.
This works, but I want to use a variable $USERNAME instead of demouser
ssh centos#$remote_host -t 'sudo sed -i "\$ademouser ALL=(ALL) NOPASSWD:ALL" /etc/sudoers'
I tried using this but it's not working.
export USERNAME=demouser
ssh centos#remote_host bash -c "'sudo sed -i "\$a$USERNAME ALL=(ALL) NOPASSWD:ALL" /etc/sudoers'"
Error: -bash: syntax error near unexpected token `('
Parameters will not expand in single quotes, one can close them, and expand in double quotes instead:
ssh user#host 'sed "s/'"$localVar"'/replacement/" file'
^^
|Enter double quotes to avoid word splitting and globbing
Exit single quotes to expand on client side.
You should however know that the command send to the server is:
sed "s/abc/replacement/" file
Which might cause problems as we are now using double quotes on the server, one can send single quotes as well, but it quickly becomes as mess:
ssh user#host 'sed '\''s/'"$localVar"'/replacement/'\'' file'
^ ^
| Escaped remote single quote
Close local single quote
This will become:
sed 's/abc/replacement' file
I have a command like this:
ssh user#hostname 'sed -e "s|foo|${bar}|" /home/data/base_out.sql > /home/data/out.sql'
The sed command is working in local shell. But it is not expanding the variable over ssh command. Thanks!
The rule is that within single quotes, parameters are not expanded. You have single quotes around the entire command.
Try this:
ssh user#hostname "sed -e 's|foo|$bar|' /home/data/base_out.sql > /home/data/out.sql"
Now $bar is expanded before the command string is passed as an argument to ssh, which is what you want.
I removed the curly braces around ${bar} because I believe they offer a false sense of security. In this case, they are not protecting you against any of the issues associated using shell variables in sed commands.
This question already has answers here:
Expansion of variables inside single quotes in a command in Bash
(8 answers)
Closed 22 days ago.
I want to use sed with a variable. My script:
input_variable="test" &&
ssh root#192.168.7.2 'cd /path/to/file && sed -i "s/this is not/this is a $input_variable/g" text.txt'
My script is supposed to change this is not into this is a test
However it changes it to this is a and somehow ingnoring the variable input_variable
Anyone an idea?
You're not interpolating that variable because you are using single quotes. I recommend continuing to use single quotes except for around the variable where you should switch to double quotes:
input_variable="test" &&
ssh root#192.168.7.2 'cd /path/to/file && sed -i "s/this is not/this is a '"$input_variable"'/g" text.txt'
Environment variables will not be replace in single quoted strings. Did you try:
input_variable="test" &&
ssh root#192.168.7.2 "cd /path/to/file && sed -i \"s/this is not/this is a ${input_variable}/g\" text.txt"