How to escape backticks in bash - bash

I am trying to escape backtick in bash for long time.
I tried escaping with \ but it does not work.
Is it possible to escape backtick in bash?
Sample code
I="hello.pdf"
var1=`cat <<EOL
![](../images/${I%.*}.png)
\`\`\`sql
some code here
\`\`\`
EOL`
echo "$var1"
Required output
![](../images/hello.png)
```sql
some code here
```

Use $(...) instead of backtick syntax for the outer command substitution. Thus:
I='foo.png'
var1=$(cat <<EOL
![](../images/${I%.*}.png)
\`\`\`sql
some code here
\`\`\`
EOL
)
echo "$var1"
See this running, and emitting your desired output, at https://ideone.com/nbOrIu
Otherwise, you need more backslashes:
I='foo.png'
var1=`cat <<EOL
![](../images/${I%.*}.png)
\\\`\\\`\\\`sql
some code here
\\\`\\\`\\\`
EOL
`
echo "$var1"
...and if you were to nest backticks inside backticks, you'd need to multiply your backslashes yet again. Just Say No to backtick-based command substitution.
By the way, something you might consider to evade this problem altogether:
I='foo.png'
fence='```'
var1=$(cat <<EOL
![](../images/${I%.*}.png)
${fence}sql
some code here
${fence}
EOL
)
echo "$var1"
...putting the literal backticks in a variable means you no longer need any kind of escaping to prevent them from being treated as syntax.

Related

How to understand quotes in command-substitution which surrounded by double-quotes in Bash?

$ a=33
$ echo "$(echo '$a')" # (1)
$a
$ echo "$(echo "$a")" # (2)
33
I can't understand the shell command-line parsing result above.
For command line (1), according to man bash, single quote inside the double-quotes will be parsed as literal, and $a inside the double quotes will be interpolated, so I think the result of command line (1) should be '33'.
You don't have single-quotes in double-quotes. $(....) is a command substitution. Essentially what occurs within (...) takes place within its own subshell. You must employ quoting rules within that subshell. The subshell represents its own environment.
For example:
$ a=33
$ echo $(echo "'$a'") # single-quotes within double-quotes
The quoting rules within the command substitution are applied correctly resulting in the output:
$ '33'
Let me know if you have further questions.

BASH scripting: when to include the back slash symbol

I am writing a BASH script and I am using the bash command. Which one of the following is correct (or are both incorrect)?
bash $pbs_dir/${module_name}.${target_ID}.${instance_ID}.pbs
or
bash \$pbs_dir/\${module_name}.\${target_ID}.\${instance_ID}.pbs
\$ will be expanded to literal $, so there is a big difference:
$ a="hello"
$ echo $a
hello
$ echo \$a
$a
Also note that you almost always want to double quote your parameter expansions to avoid word splitting and pathname expansion:
echo "$a"
So you properly want to use the following:
bash "$pbs_dir/${module_name}.${target_ID}.${instance_ID}.pbs"

possible bashism: echo -e

I am using following shebang in my script:
#!/bin/sh
To check whether I haven't used any bash syntax, I checked my script with checkbashisms script and it says
possible bashism in my_script.sh line 3 (echo -e):
echo -e "hello world"
And I am running this script on embedded board with busybox shell.
How to resolve this?
POSIX allows echo -e as the default behavior. You may do
var="string with escape\nsequence"
printf "%s\n" "$var" # not interpreting backslashes
printf "%b\n" "$var" # interpreting backslashes
This should pass the checkbashisms test
help echo
-e enable interpretation of the following backslash escapes
...
If your code doesn't need to interpret backslash escapes then you can safely remove the -e flag.
Sometimes, people tend to use -e just for interpreting \n as newline. If that's the case, know that you can have multiline strings just by quoting them and writing as it is. An example:
var="Hi,
I am
a multiline
string"
But if you do need to interpret backslash escapes, then using printf will be your best bet.
Though I would recommend using printf whether you need backslash interpretation or not.
With printf:
printf "%s\n" "$var" # no backslash interpretation
printf "$var" # backslash interpretation occurs

escape curly braces in unix shell script

I have a string:
{2013/05/01},{2013/05/02},{2013/05/03}
I want to append a { at the beginning and a } at the end. The output should be:
{{2013/05/01},{2013/05/02},{2013/05/03}}
However, in my shell script when I concatenate the curly braces to the beginning and end of the string, the output is as follows:
{2013/05/01} {2013/05/02} {2013/05/03}
Why does this happen? How can I achieve my result? Am sure there is a simple solution to this but I am a unix newbie, thus would appreciate some help.
Test script:
#!/usr/bin/ksh
valid_data_range="{2013/05/01},{2013/05/02},{2013/05/03}"
finalDates="{"$valid_data_range"}"
print $finalDates
The problem is that when you have a list in braces outside quotes, the shell performs Brace Expansion (bash manual, but ksh will be similar). Since the 'outside quotes' bit is important, it also tells you how to avoid the problem — enclose the string in quotes when printing:
#!/usr/bin/ksh
valid_data_range="{2013/05/01},{2013/05/02},{2013/05/03}"
finalDates="{$valid_data_range}"
print "$finalDates"
(The print command is specific to ksh and is not present in bash. The change in the assignment line is more cosmetic than functional.)
Also, the brace expansion would not occur in bash; it only occurs when the braces are written directly. This bilingual script (ksh and bash):
valid_data_range="{2013/05/01},{2013/05/02},{2013/05/03}"
finalDates="{$valid_data_range}"
printf "%s\n" "$finalDates"
printf "%s\n" $finalDates
produces:
ksh
{{2013/05/01},{2013/05/02},{2013/05/03}}
{2013/05/01}
{2013/05/02}
{2013/05/03}
bash (also zsh)
{{2013/05/01},{2013/05/02},{2013/05/03}}
{{2013/05/01},{2013/05/02},{2013/05/03}}
Thus, when you need to use the variable $finalDates, ensure it is inside double quotes:
other_command "$finalDates"
if [ "$finalDates" = "$otherString" ]
then : whatever
else : something
fi
Etc — using your preferred layout for whatever you don't like about mine.
You can say:
finalDates=$'{'"$valid_data_range"$'}'
The problem is that the shell is performing brace expansion. This allows you to generate a series of similar strings:
$ echo {a,b,c}
a b c
That's not very impressive, but consider
$ echo a{b,c,d}e
abc ace ade
In order to suppress brace expansion, you can use the set command to turn it off temporarily
$ set +B
$ echo a{b,c,d}e
a{b,c,d}e
$ set -B
$ echo a{b,c,d}e
abe ace ade

sed won't perform the required subs inside shell script

In the below shell script I try to print A2D(Vlog-Ams-#Cross) with special characters escaped. For example replace ( with \( but sed won't have any effect.
#! /bin/sh
parameter="A2D(Vlog-Ams-#Cross)"
echo $parameter
parameterz=`echo "$parameter" | sed 's/(/\\(/g'`
echo $parameterz
The output is
A2D(Vlog-Ams-#Cross)
A2D(Vlog-Ams-#Cross)
If I do the same on my c-shell terminal, it works fine.
Any ideas?
You use backslashs within a backtick command and that's tricky. If the sed command didn't occur within backticks, it would work correctly. When the shell looks for the closing backtick, however, it removes one level of backslash quoting, so you get
sed 's/(/\(/g'
and that's a no-op. If your shell permits it, use $(...) instead of backticks; in this way you avoid these quoting problems.
In your replacement \\( the first \ escapes the second \. But you must escape the (, too:
$ echo 'A2D(Vlog-Ams-#Cross)' | sed -e 's/(/\\\(/g' -e 's/)/\\\)/g'
A2D\(Vlog-Ams-#Cross\)

Resources