Using sed command in shell script - linux

This is my simple shell script
sample.sh
LOCALCONFIGDIR="Install"
CONFLOC="$LOCALCONFIGDIR/server.conf"
echo "Enter Web Url:"
read weburl
echo "sed 's/^\(ServerName\)$/\1 "$weburl"/' "$CONFLOC
sed "'s/^\(ServerName\)$/\1 "$weburl"/' "$CONFLOC
When I run this code, I get the result in echo command as following.
sed 's/^\(ServerName\)$/\1 www.weburl.com/' Install/server.conf
But when executing sed command in the next line, It says the below error.
sed: -e expression #1, char 1: unknown command: `''
I tried the command produced in echo statement from Terminal screen, It is working. But Line number 5, doesn't working from shell script

You need to use one set of quotes, not two, and since you want the $weburl variable expanded, you need to use double quotes:
sed "s/^\(ServerName\)$/\1 $weburl/" "$CONFLOC"
That'll be OK as long as $weburl doesn't contain any slashes. If it does, you need to use a different character than /, such as %, to separate the parts of the substitute command:
sed "s%^\(ServerName\)$%\1 $weburl%" "$CONFLOC"

Related

How do I run sed in TCL

I am trying to use TCLs builtin exec procedure to run the following sed shell command:
sed -i 's/"VALUE.${name}">.*</"VALUE.${name}">${value}</' ${dir}/imp.xml
However when I pass it to exec tcl errors out with
sed: -e expression #1, char 1: unknown command: `''
no idea how to interpret this.
I tried escaping the exec string:
exec {sed -i 's/"VALUE.${name}">.*</"VALUE.${name}">${value}</' ${dir}/imp.xml}
However this prevents the tcl variables from being expanded inside of the string.
Does anyone know what I need to do to get tcl to exec this sed program?
(my shell is csh if that is relevant)
The final solution involved 2 changes to the command string,
Escape all the double quote characters, (thanks #Chris Heithoff)
Single quotes are handled funny by TCL, replacing them with double quotes
(that are not escaped!) resolves the issue.
The final, working command string:
exec sed -i "s/\"VALUE.${name}\">.*</\"VALUE.${name}\">${alue}</" ${dir}/impl.xml
Each argument to the exec command must correspond to an individual argument at the shell command line, so enclosing everything in {} doesn't work.
Try this:, where all double quotes and dollar signs are escaped.
exec sed -i 's/\"VALUE.\${name}\">.*</\"VALUE.\${name}\">\${value}' \${dir}/impl.xml

How to run sed on remote server using ssh inside a shell script(variables included)

I have a situation here, I am trying to run a sed command on a remote shell inside my shell script and using variables that are dynamic and end up getting the same error again and again.
This is the sed command that is running fine on local shell without any error. I have used this regular expression after thorough testing and trust me there is no problem with it.
sed -i 's/ #0\t30718/ 0\t30718/' ./config.txt
Trying to run this in a remote shell using ssh:
ssh root#sys_name sed -i 's/ #0\t30718/ 0\t30718/' /absolute-path/vconfig.txt
And when I try to run this command using variables. (30718 and path of the file are the variables):
ssh root#sys_name 'sed -i "s/0\t${pe_list[0]}/#0\t${pe_list[0]}/g" $file_path'
or like this:
ssh root#sys_name "sed -i 's/0\t${pe_list[0]}/#0\t${pe_list[0]}/g' $file_path"
I either get the sed: -e expression #1, char 2: unterminated `s' command error or the sed command executes with undesired output matching the variable names as is. Basically, put in few words, I want to execute a sed command on a remote shell using ssh, and the constraint is that the entire command is part of a script and the values to be matched and the filename are variables in that file.
You have variable set in your local shell, but is is not sed variable, so you should exit sed environment by closing it with single quote, put your variable, then open again with single quote and continue sed stuff:
sed -e 's/Red Hat/'${z}'/' /etc/redhat-release
In case your $z variable contains spaces, you need to embrace it with double quotes:
sed -e 's/Red Hat/'"${z}"'/' /etc/redhat-release
Finally, when you sending your command through ssh you are also adding double quotes around whole command, so all double quotes used in this command should be escaped, else everything between these will be evaluated locally on your source host. So do like this:
z="BLACK HAT"
ssh root#sys_name "sed -e 's/Red Hat/'\"${z}\"'/' /etc/redhat-release"
You will get:
BLACK HAT Enterprise Linux Server release 6.10 (Santiago)

Linux: Append variable to end of line using line number as variable

I am new to shell scripting. I am using ksh.
I have this particular line in my script which I use to append text in a variable q to the end of a particular line given by the variable a
containing the line number .
sed -i ''$a's#$#'"$q"'#' test.txt
Now the variable q can contain a large amount of text, with all sorts of special characters, such as !##$%^&*()_+:"<>.,/;'[]= etc etc, no exceptions. For now, I use a couple of sed commands in my script to remove any ' and " in this text (sed "s/'/ /g" | sed 's/"/ /g'), but still when I execute the above command I get the following error
sed: -e expression #1, char 168: unterminated `s' command
Any sed, awk, perl, suggestions are very much appreciated
The difficulty here is to quote (escape) the substitution separator characters # in the sed command:
sed -i ''$a's#$#'"$q"'#' test.txt
For example, if q contains # it will not work. The # will terminate the replacement pattern prematurely. Example: q='a#b', a=2, and the command expands to
sed -i 2s#$#a#b# test.txt
which will not append a#b to the end of line 2, but rather a#.
This can be solved by escaping the # characters in q:
sed -i 2s#$#a\#b# test.txt
However, this escaping could be cumbersome to do in shell.
Another approach is to use another level of indirection. Here is an example of using a Perl one-liner. First q is passed to the script in quoted form. Then, within the script the variable assigned to a new internal variable $q. Using this approach there is no need to escape the substitution separator characters:
perl -pi -E 'BEGIN {$q = shift; $a = shift} s/$/$q/ if $. == $a' "$q" "$a" test.txt
Do not bother trying to sanitize the string. Just put it in a file, and use sed's r command to read it in:
echo "$q" > tmpfile
sed -i -e ${a}rtmpfile test.txt
Ah, but that creates an extra newline that you don't want. You can remove it with:
sed -e ${a}rtmpfile test.txt | awk 'NR=='$a'{printf $0; next}1' > output
Another approach is to use the patch utility if present in your system.
patch test.txt <<-EOF
${a}c
$(sed "${a}q;d" test.txt)$q
.
EOF
${a}c will be replaced with the line number followed by c which means the operation is a change in line ${a}.
The second line is the replacement of the change. This is the concatenated value of the original text and the added text.
The sole . means execute the commands.

How to pass sed command with spaces in expression to Bash function through $#

I would need to replace a string having spaces with another string in a file in a bash script where all calls should be done through a function that writes the command to a log file and then runs the command. The logrun function uses special character $# for reading in the command. I'm trying to use sed for replacing but I can't find a way to escape spaces when the sed command having spaces in expression parameter goes through $#.
I have simplified the problem to test scripts where I use sed for replacing a c with a b c.
test1.sh works great:
#!/bin/bash
TESTFILE=/tmp/test.txt
echo "a c" > $TESTFILE
sed -i -e 's/a c/a b c/' $TESTFILE
test2.sh fails:
#!/bin/bash
function logrun() {
CMD=$#
$CMD
}
TESTFILE=/tmp/test.txt
echo "a c" > $TESTFILE
logrun sed -i -e 's/a c/a b c/' $TESTFILE
Result:
sed: -e expression #1, char 3: unterminated `s' command
The reason for error is the space(s) in the -e expression. I haven't found a way to call sed through that function. I have tried to use double quotes instead of single quotes and to escape spaces with a backslash etc. I am really curious to find out what's the correct way to do it.
logrun() {
CMD=("$#")
"${CMD[#]}"
}
Writing $# without quotes combines all of the arguments into one space-separated string. "$#" with quotes keeps each argument separate and preserves whitespace.
Writing just CMD="$#" would create a simple string variable. CMD=("$#") creates an array.
Then, to expand the array, use the same syntax as you did with PARAMS: "${CMD[#]}". The quotes and the two sets of braces are all necessary. Don't leave any of them out.
By the way, if you don't need the CMD variable, it could be a lot less verbose:
logrun() {
"$#"
}

How to use sed with a variable that needs to be escaped

I have a file, and I am trying to use bask to replace all the contents of a substring with a path.
I can use the command:
sed -i s/{WORKSPACE}/$MYVARIABLE/g /var/lib/jenkins/jobs/MY-JOB/workspace/config/params.ini
My config/params.ini looks like:
[folders]
folder1 = {WORKSPACE}/subfolder1
folder2 = {WORKSPACE}/subfolder2
however, when $MYVARIABLE is a path, it fails (containing slashes), the sed command fails with:
sed: -e expression #1, char 16: unknown option to `s'
When I run through it manually, I see that the $MYVARIABLE needs to have it's path-slashes escaped. How can I modify my sed command to incorporate an escaped version of $MYVARIABLE?
There's nothing saying you have to use / as your delimiter. sed will use (almost) anything you stick in there. I have a tendency to use |, since that never (rarely?) appears in a path.
sridhar#century:~> export boong=FLEAK
sridhar#century:~> echo $PATH | sed "s|/bin|/$boong|g"
~/FLEAK:/usr/local/FLEAK:/usr/local/sbin:/usr/local/games:/FLEAK:/sbin:/usr/FLEAK:/usr/sbin:/usr/games:/usr/lib/lightdm/lightdm:/home/oracle/app/oracle/product/12.1.0/server_1/FLEAK
sridhar#century:~>
Using double-quotes will allow the shell to do the variable-substitution.
Just escape the $ sign, and use a different delimiter:
sed -i 's;{WORKSPACE};\$MYVARIABLE;g' your_file

Resources