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

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

Related

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

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}"

Wrapper function for sed that takes regex search/replace string as parameters

I'm trying to create a sed wrapper that first checks if the file exists, if it does, run with the specified parameters. e.g.:
sed_wrapper 's/replace this/with this/g' test_file.txt
My attempt works fine if there are no spaces in the regex, but as soon as spaces are added it breaks.
To generalize, how can I take a function's parameter that contains spaces and quotations and run it as a command within the function?
The script:
#!/bin/bash
# ./test_script.sh
sed_wrapper() {
ALL_PARAMETERS=($#)
ALL_PARAMETERS_LENGTH=${#ALL_PARAMETERS[#]}
PARAMETER_FILE=${ALL_PARAMETERS[$ALL_PARAMETERS_LENGTH_-1]}
PARAMETER_REGEX=${ALL_PARAMETERS[#]:0:$ALL_PARAMETERS_LENGTH-1}
echo "ALL_PARAMETERS: $ALL_PARAMETERS"
echo "-------------------------------"
if [ -f "$PARAMETER_FILE" ] ; then
sed $PARAMETER_REGEX $PARAMETER_FILE
fi
}
sed_wrapper 's/#REPLACETHIS/\0--->simple_example/g' test_file.txt
echo "************************************************************"
sed_wrapper 's/#REPLACETHIS/\0--->complex example/g' test_file.txt
echo "************************************************************"
sed_wrapper "'s/#REPLACETHIS/\0--->quotation_example/g'" test_file.txt
Contents of test_file.txt:
#REPLACETHIS
Output of running ./test_script.sh:
ALL_PARAMETERS: s/#REPLACETHIS/\0--->simple_example/g test_file.txt
-------------------------------
#REPLACETHIS--->simple_example
************************************************************
ALL_PARAMETERS: s/#REPLACETHIS/\0--->complex example/g test_file.txt
-------------------------------
sed: -e expression #1, char 28: unterminated `s' command
************************************************************
ALL_PARAMETERS: 's/#REPLACETHIS/\0--->quotation_example/g' test_file.txt
-------------------------------
sed: -e expression #1, char 1: unknown command: `''
Expected output of running ./test_script.sh:
ALL_PARAMETERS: s/#REPLACETHIS/\0--->simple_example/g test_file.txt
-------------------------------
#REPLACETHIS--->simple_example
************************************************************
ALL_PARAMETERS: s/#REPLACETHIS/\0--->complex example/g test_file.txt
-------------------------------
#REPLACETHIS--->complex example
************************************************************
ALL_PARAMETERS: 's/#REPLACETHIS/\0--->quotation_example/g' test_file.txt
-------------------------------
#REPLACETHIS--->quotation_example
When running the final sed command, you can use the original parameters:
Use the quoted $#. It will make sure all parameters are quoted properly.
sed "$#"
Instead of:
sed $PARAMETER_REGEX $PARAMETER_FILE
There are simpler constructs in bash to perform this task of creating 'silent_sed'. (Logging statement removed from function for simplicity)
sed_wrapper() {
local PARAMETER_FILE=${#:#$}
if [ -f "$PARAMETER_FILE" ] ; then
sed "$#"
fi
}

Bash script: Using variables in executing sed in Freebsd which expects \ afters a

I'm trying to use variables in a sed command in Freebsd. sed in Freebsd expects \ after a. Basically I want to append a line if a particular line in the file matches a pattern. I'm using sed's append for that.
#!/usr/bin/bash
SYSLOG_SERVER="192.168.1.36"
SYSLOG_PORT="514"
syslog_conf_file="/etc/syslog.conf"
send_logs() {
logs=(messages auth.log )
send_logs[0]=`awk '(index($2, "messages") != 0) {print $1}' $syslog_conf_file`
send_logs[1]=`awk '(index($2, "auth.log") != 0) {print $1}' $syslog_conf_file`
for (( i = 0 ; i < ${#send_logs[#]} ; i++ ))
do
if [ ! -z "${send_logs[$i]}" ]; then
send_logs[i]=${send_logs[i]}" \t"#$SYSLOG_SERVER:$SYSLOG_PORT
sed "/${logs[$i]}$/a\
${send_logs[$i]} \
" $syslog_conf_file
fi
done
}
I'm facing this error. The variables are printed properly but the way in which I'm running the script is wrong. How can I fix this ?
root#Great# bash temp.sh
send_logs *.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err \t#192.168.1.36:514
logs messages
sed: 1: "/messages$/a ...": command a expects \ followed by text
send_logs auth.info;authpriv.info \t#192.168.1.36:514
logs auth.log
sed: 1: "/auth.log$/a ...": command a expects \ followed by text
Sample expected input for sed:
root#Great# sed '/messages$/a\
*.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err #192.168.1.36:514 \
' /etc/syslog.conf
Expected output:
*.err;kern.warning;auth.notice;mail.crit /dev/console
*.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err /var/log/messages
*.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err #192.168.1.36:514
security.* /var/log/security
auth.info;authpriv.info /var/log/auth.log
It's because \ followed by a newline character means following line to be joined, to avoid escape : \\ :
sed "/${logs[$i]}$/a\\
${send_logs[$i]} \\
" $syslog_conf_file

Unable to define line number in sed by variable

I'm trying to use an array to define the lines to replace using sed; I can delete the lines using a variable for the line number but I can't get sed to use the variable to define the line number to write to. The problem seems to reside in the insert line. How do you pass the value of an array as a line number to sed?
#!/bin/bash
lineNum=$(sed -n '/max_allowed_packet/=' /etc/mysql/my.cnf)
IFS= #There's a space as the delimiter#
ary=($lineNum)
#for key in "${!ary[#]}";
# do
# sed -i '$ary[$key]'d /etc/mysql/my.cnf;
# #The folllowing line errors#
# sed -i "'$ary[$key]'imax_allowed_packet = 32M" /etc/mysql/my.cnf;
# #The above line errors#
#done
#for val in "${ary[#]}";
# do
# sed -i "${val}d" /etc/mysql/my.cnf;
# sed -i "${val}imax_allowed_packet = 32M" /etc/mysql/my.cnf;
# done
for val in "${ary[#]}";
do
sed -i "${val}s/.*/imax_allowed_packet = 32M" /etc/mysql/my.cnf";
done
For the first stanza of script I get the following output:
Error: sed: -e expression #1, char 1: unknown command: `''
For the second Stanza I get the following output:
sed: -e expression #1, char 3: unknown command:
'
sed: -e expression #1, char 3: unknown command:
'
For the third Stanza I get the following output:
./test.sh: line 22: unexpected EOF while looking for matching `"'
./test.sh: line 24: syntax error: unexpected end of file
Edit, rewriting the sed commands as sed -i "${ary[$key]}" generates the following error output: sed: -e expression #1, char 3: unknown command: `
I think you're over-complicating the issue. Your script can be reduced to this:
sed 's/\(max_allowed_packet\).*/\1 = 32M/' /etc/mysql.cnf
This performs a substitution on every occurrence of max_allowed_packet, setting the rest of the line to = 32M. Add the -i switch to overwrite the file when you're happy with the result.
Problems with your attempt
Shell parameters are not expanded within single quotes, so you would need to use double quotes, e.g. sed -i "${ary[$key]}d". You can use set -x to see what is happening here - at the moment, you will see the literal string $ary[$key], rather than the array value.
If I understand your intention correctly (you want to substitute the entire line), there's no need to call sed twice:
for val in "${ary[#]}"; do
sed -i.bak "${val}s/.*/imax_allowed_packet = 32M" /etc/mysql/my.cnf
done
I have chosen to loop through the values of the array, instead of the keys, in order to simplify things a little. When using the -i option, it is always a good idea to specify a backup file, as I have done.

sed (replacing / with \/ using shell)

I'm using a shell script that uses sed
I have this sentence in a variable
kpi="ENFRIADORA CONDENSADA POR AIRE/AIRE-AIRE/AGUA - MENSUAL"
if in a console I put
echo $kpi | sed 's/\//\\\//g'
I see
ENFRIADORA CONDENSADA POR AIRE\/AIRE-AIRE\/AGUA - MENSUAL
That is what I want, but when I put this in a script like this
echo start
echo $kpi2
kpi_2=`echo $kpi2 | sed 's/\//\\\//g'`
echo $kpi_2
echo end
That I see is :
start
ENFRIADORA CONDENSADA POR AIRE/AIRE-AIRE/AGUA - MENSUAL
sed: -e expresion #1, character 9: unknown option to `s'
end
Any suggestion?
$> kpi_2=$( echo $kpi | sed 's/\//\\\//g' )
$> echo $kpi_2
ENFRIADORA CONDENSADA POR AIRE\/AIRE-AIRE\/AGUA - MENSUAL
This works for me:
kpi_2=`echo $kpi2 | sed 's:\/:\\\/:g'`

Resources