Shell sed - "unterminated `s' command" in Windows / "unescaped newline inside substitute pattern" in MAC - windows

I am trying to fix an old shell script that used to run on MAC to be runnable on Windows... But I am facing errors in both machines WRT one particular sed operation. The code snippet is :
echo "1 :: ${1}"
echo "2 :: ${2}"
sed -i.bak 's/^export \('${1}'=\)\(.*\)/export \1"'"$(sedscape ${2})"'"/' ~/.bash_profile
rm -f ~/.bash_profile.bak
The function sedscape is :
function sedscape() {
echo " >>> sedscape"
echo "1 :: ${1}"
echo ${1//\//\\/} | sed 's/'\''/'\'\\\\\'\''/'
}
This gives me following error on Windows:
1 :: AWS_ACCESS_KEY
2 ::
sed: -e expression #1, char 59: unterminated `s' command
and on MAC:
1 :: AWS_ACCESS_KEY
2 ::
sed: 1: "s/^export (AWS_ACCESS_ ...": unescaped newline inside substitute pattern
.bash_profile has just one line :
export AWS_ACCESS_KEY="aaaa"
As far as I can understand, it is readin every line from .bash_profile starting with "export" and replacing the value of it with whatever is in "2" ... but it fails even before the "sedscape" half (second half) of the expression is evaluated.
Correct me if the understanding of the sed command is wrong.
PLEASE HELP !!!

The echos in sedscape were creating the errors... simply removing them sloved the issue.
echo " >>> sedscape"
echo "1 :: ${1}"

Related

Why sed failed with shell variables but success with their values?

I want to use sed to replace a particular string in yaml file with base64 encoded tls key:
TLS_KEY=`cat tls.key | base64`
sed -i "s/##TLS_KEY##/${TLS_KEY}/" 02-elastic-tls.yaml
Then I get this error:
sed: -e expression #1, char 90: unterminated `s' command
But if I replace ${TLS_KEY} with its value directly in the above command, it will success.
Execute echo ${TLS_KEY}:
LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZB QVNDQktjd2dnU2pBZ0VBQW9JQkFRRENtUHJVa29ibGpKT3oKOGJtMHZodzNwRHdLa0M2TGJaUjd5 enFWVkpuc2VTQkI4Z0E3aExkYmNBRDJTTWp6SDBQUEpEelE1elJ5dnJBYQpSK3N3QU1BeFhwQVdH Ulp5S2RsTkVTTDhuREZvNGJ2ODB1enQrdWZiSEFZTGl2OVByMHpRRnA2cjh5U3BlTXNkCm5xNnh1 K3ZaMHJ1ZWpxdkxhZEVSMFNra0h1VUp4bExGVjY1bzFFREdzYzhKVlBYaXFFUzdRcXhTTnhtS0Nt VzAKdFdMbWd6YUZ2d2tjcFpHbWJjTmpsMFZraG9ZTjFVZk51M0FURHJ3eUJQUmZIYWJvVGFSVlFm WmE5Q3dpSThPZgpXVzR0ZnA3eW9GcFRhSDlURUdxYldzY1VMa3MvamdlbW15eHZPY1Y0bG04SXgw dHhLT2J1R0ZWVGp2dlBnb0JuCnJLb2V5UVMzQWdNQkFBRUNnZ0VBUjEwV3o1SVV5bVh0WE5aUEJr dVp5WVgvUnRodFdWQ01YWUhBTURkZ1kycGcKUEE3bHF1NFcxLytST3NDaWdSWjhKYURpZExIMWVB Y2FTZWtLQlFhaGRQbDYyYi9GallSdlhtWGtjTU5QRTJtRgpLVWlvL3ZVK3hnblc1YkRKeEkxREhD VFBkN3VwUEVWQ0o5Q2p2Q1p3YmVkc1NzK0RqUXQzVXBOa0JRMFhiYWViCkpTVnk2ellCckFVOGZN cTV3empmTUFKVk0yZ0VaK3JYMERxc003T0IvRVpIWEI4dktkc3RKbCtWSmZWNnVBVjAKbTkxZnFG MzZmVGZYbWlxL29qMjZqdVZ1MkRBaVhqQWZQUzBRalVhOFRjVW1ZeFp4NVVaa052YWs2aGFwM1ND TwpXS2VjM0l4TWpra2xldUY0RGlBWHJHRnQ2WGxHN0RCQm13SUkrM3NRb1FLQmdRRHo2dk9HaUdn cVNQZHNaZ2lKCnd5NHhjT0JkZjRFbzRrZG9HYmduWEZ5eCtPSzczRThHZWZxdExMdjlzc2YxUUpC dmFkdFhZU21uNU5lNFBMNVoKTlFPcWxRSFhGcHhqcFA5WUxhbmdnRGR3S2ZzSVRxWnA0SDZLV0k5 aEdFeCtGcmRmUzlDY2JTTkpQcGk4dHhNVwpaV0gyeXUrZXZSS0VYYUZmMFZUZ1VMcHFUd0tCZ1FE TVBKMGVwVFg5WDluemY4Qi9VVkhKWnQ4V3dZY0Mzc1pBCnZkWUNSZFdYSm5RWE0zR2dxRTF1OGx2 dlZXNWZrMWdDNnlFWTlBdUZ1bCtGM1VoTVdRTlRhTWVpWHVCUEpJUVQKdEREalJQRmJXRGFyalo4 K0hrVXJObGdtVFEweVNhNzV1RVVhZWhqeDFjTkpLcCswSDZiQVNSRWdwWWpzdVhJSQpsaUk3ZGw5 dEdRS0JnUUNLZHA2bGlUdXdmVmxQUktDbUs1RkdhYkJFQTBSN3cvQUxMVVozdVp1NVAvTGQ5OU00 CmR2Z1JaR3FYT3V6OTBSZnMxeWUzYzZXazlHaHM0cmFmaDFPOGV2ZmZkS3QwZVU2bWJNMlpicytK c1pzYWZTTkUKeVRhc0xGZkFJMzRRdWE2QXYxWDk1b3A0WXJ0cnJYVjlhakh4V2dRcWxXUTBsYjRz MlhVWUhWdWxTd0tCZ0Q4Mwo2L0tXZFJYTzI2b1J1MFl0cDhGTnhIUkl4ei9PTVZQTTd6ZVk0anA5 UHFZSDJINUFXbWVqUVczZDVlSlR1NFI3CnY2ejNyYkZoTlR3OGVLcVpTdnhBakxybjMwcmdKTG5z cHMxU2c5c2dmUnV4SkwrWG94VnpKdW9FSTdlVE0wUTkKRTdiVVlIQkxHTDNISWRRaGovNHBIOUla S3o4TFVBNzBXZmhKOWRQUkFvR0FjNG5XYnU4Q0tFRzBPSCtmKzYrSAo1bnNmaDc3UUhiZEJLK2Za ZXQybFhrMjREUUlxUGZCVUR6clpINTVxenZPb2Z5T2tRbzI3cGZBT1gwS1l6dHBECm54cUVWd2kr WHhOaTAvRUxSSTdEanc5KzF4TkQ0N3NZTFhyd2dMZHpWQWtRengrSXM4Y3JGQU9iMi92cGNNYm0K RU4wNzJOV1lXUy9LZllzdXQ0Z2ZONVE9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
so why I got this error?
Note the difference between echo ${TLS_KEY} and echo "${TLS_KEY}".
$ x="123
> 456"
$ echo $x
123 456
$ echo "$x"
123
456
I suspect there are newline characters present in your key which breaks sed.
$ echo abc | sed "s/abc/$x/"
sed: -e expression #1, char 7: unterminated `s' command

Replace strings with variable in bash script

I want to create a bash script to change the configuration file of an application. The script will read a variable and replace the value of a setting that I want to change with the variable value.
#!/bin/bash
mysqlurlenv1="jdbc:mysl://xx.xx.xx.xx:3306
mysqlurlenv2="jdbc:mysl://xx.xx.xx.xz:3306
configFile=app.conf
pattern=$1
case "$pattern" in
1)
sed -i.bak "s/^\(mysql.db.url =\).*/\1 ${mysqldburl_env1}/"
;;
2)
sed -i.bak "s/^\(mysql.db.url =\).*/\1 ${mysqldburl_env2}/"
;;
*)
echo "Wrong input...try again"
esac
I have a config file with the following entry
mysql.db.driver = com.mysql.jdbc.Driver
mysql.db.url = jdbc:mysql....
mysql.db.uname = admin
When I run the script I got this error
sed: -e expression #1, char 40: unknown option to `s'
How to get those defined variable in the config file ? Any help will appreciated
Rgds
Din
You are using this sed pattern s/FIND_STRING/REPLACE_STRING, that is the common way to do it.
But your REPLACE_STRING contains /, so your pattern will become s/FIND_STRING/jdbc:mysl://.... and that is invalid, because it contains too much /.
Sed accepts any character as field separator, so in your case you need change sed pattern field separator from / to something else, like |.
Example:
$ mysqlurlenv1="jdbc:mysl://xx.xx.xx.xx:3306"
$ echo "mysql.db.url = jdbc:mysql" | sed "s|^\(mysql.db.url =\).*|\1 ${mysqlurlenv1}|"
mysql.db.url = jdbc:mysl://xx.xx.xx.xx:3306

Net::OpenSSH command remote with multi pipeline

i have a problem when attempt run multi command in remote linux, with Perl and Module Net::OpenSSH. .
use Net::OpenSSH;
my $new_connect = Net::OpenSSH->new($D_CONNECT{'HOST'}, %OPT);
my $file = "file.log.gz"
my ($output2, $error2) = $new_connect->capture({ timeout => 10 }, "gunzip -c /path/to/file/$file | tail -n1 | awk '/successfully completed/ {print \$NF}'");
the output that i get is:
bash: -c: line 1: syntax error near unexpected token |'
bash: -c: line 1: |tail -n1 |awk '/successfully completed/ {print $NF}''
;;;
any idea or suggestion, thanks.
Fcs
Probably a quoting error. Just let Net::OpenSSH take care of the quoting for you:
my ($output2, $error2) = $new_connect->capture({ timeout => 10 },
'gunzip', '-c', "/path/to/file/$file", \\'|',
'tail', '-n1', \\'|',
'awk', '/successfully completed/ {print $NF}');
Note how the pipes (|) are passed as a double reference so that they are passed unquoted to the remote shell. The module documentation has a section on quoting.
That looks like the error message you'd get if you had a newline at the end of your $file string, causing the pipe character to be at the start of a second line (interpreted as the start of a second command).
This test deomstrates the same error:
bash -c 'echo foo
| cat'
So I guess your bug doesn't really occur with $file = "file.log.gz" and whatever your real $file is, you need to chomp it.
A bigger mystery is why bash says the error is on line 1 of the -c. ash, ksh, and zsh all correctly report it on line 2.

replace and delete characters in a shell script

I have a shell script to automate builds of my programm. I need to transform versioning numbers like V4_5_1-RC1 to 4.5.1-RC1. The V should be removed and the _ should be replaced with .. I tried several things, for example with sed:
$NAMEEXT = "V4_5_1-RC1"
$lffNameRSC = ${sed -e "s/V//g" <<< $NAMEEXT}
$lffNameRSC = ${sed -e "s/_/./g" <<< $lffNameRSC}
echo $lffNameRSC
but I'm getting errors.
./makerelease.sh: line 113: ${sed -e "s/V//g" <<< $NAMEEXT}: bad substitution
./makerelease.sh: line 114: ${sed -e "s/_/./g" <<< $lffNameRSC}: bad substitution
there should be no spaces around =
there should be $(..) instead of ${..} to evaluate the command
there should not be $ in variable assignment statement
With
#!/bin/bash
NAMEEXT="V4_5_1-RC1"
lffNameRSC=$(sed -e "s/V//g" <<< $NAMEEXT)
lffNameRSC=$(sed -e "s/_/./g" <<< $lffNameRSC)
echo $lffNameRSC
you will get
4.5.1-RC1
And, by the way, it could be done easier, like
$> echo "V4_5_1-RC1" | sed "s/V//g; s/_/./g"
4.5.1-RC1
Bash parameter expansion can do what you want without any external tools:
NAMEEXT="V4_5_1-RC1"
version=${NAMEEXT#V} # remove the leading V
version=${version//_/.} # replace all _ with .
echo $version # ==> 4.5.1-RC1

replace first line of files by another made by changing path from unix to windows

I am trying to do a bash script that:
loop over some files : OK
check if the first line matches this pattern (#!f:\test\python.exe) : OK
create a new path by changing the unix style to windows style : KO
Precisely,
From: \c\tata\development\tools\virtualenvs\test2\Scripts\python.exe
I want to get: c:\tata\development\tools\virtualenvs\test2\Scripts\python.exe
insert the new line by appending #! and the new path : KO
Follow is my script but I'm really stuck!
for f in $WORKON_HOME/$env_name/$VIRTUALENVWRAPPER_ENV_BIN_DIR/*.py
do
echo "----"
echo file=$f >&2
FIRSTLINE=`head -n 1 $f`
echo firstline=$FIRSTLINE >&2
unix_path=$WORKON_HOME/$env_name/$VIRTUALENVWRAPPER_ENV_BIN_DIR/python.exe
new_path=`echo $unix_path | awk '{gsub("/","\\\")}1'`
echo new_path=$new_path >&2
# I need to change the new_path by removing the first \ and adding : after the first letter => \c -> c:
new_line="#!"$new_path
echo new_line=$new_line >&2
case "$FIRSTLINE" in
\#!*python.exe* )
# Rewrite first line
sed -i '1s,.*,'"$new_line"',' $f
esac
done
Output:
file=/c/tata/development/tools/virtualenvs/test2/Scripts/pip-script.py
firstline=#!f:\test\python.exe
new_path=\c\tata\development\tools\virtualenvs\test2\Scripts\python.exe
new_line=#!\c\tata\development\tools\virtualenvs\test2\Scripts\python.exe
Line that is written in the file: (some weird characters are written I do not know why...)
#!tatadevelopment oolsirtualenvs est2Scriptspython.exe
Line I am expecting:
#!c:\tata\development\tools\virtualenvs\test2\Scripts\python.exe
sed is interpreting the backslashes and characters following them as escapes, so you're getting, e.g. tab. You need to escape the backslashes.
sed -i "1s,.*,${new_line//\\/\\\\}," "$f"

Resources