Difference between $(command) and `command` in a script [duplicate] - linux

This question already has answers here:
Command substitution: backticks or dollar sign / paren enclosed? [duplicate]
(3 answers)
Closed 9 years ago.
What is the difference between executing a command like this:
var=$(ls -alh /dir)
And doing it like this:
var=`ls -alh /dir`
Is one method able to be used in more interpreters than the other?

They are both command substitution
Section 3.5.4 http://www.gnu.org/software/bash/manual/bashref.html
Bash performs the expansion by executing command and replacing the
command substitution with the standard output of the command, with any
trailing newlines deleted. Embedded newlines are not deleted, but they
may be removed during word splitting. The command substitution $(cat
file) can be replaced by the equivalent but faster $(< file).
When the old-style backquote form of substitution is used, backslash
retains its literal meaning except when followed by ‘$’, ‘`’, or ‘\’.
The first backquote not preceded by a backslash terminates the command
substitution. When using the $(command) form, all characters between
the parentheses make up the command; none are treated specially.
Command substitutions may be nested. To nest when using the backquoted
form, escape the inner backquotes with backslashes.
If the substitution appears within double quotes, word splitting and
filename expansion are not performed on the results.

Related

grep line from text file including brackets [duplicate]

This question already has answers here:
grep to find literal [square brackets] with specific data
(2 answers)
Closed last month.
I have a file called a.txt
something [low] https://url/low.txt
something [info] http://url1/low.txt
something [low] https://url2/robots.txt
How can i achieve this output using grep command?
something [low] https://url/low.txt
something [low] https://url2/robots.txt
thanks in advance
grep 'something \[low\]' a.txt
The single quotes are to prevent the shell from interpreting the brackets (and breaking on the space).
grep itself uses brackets for simple regular expressions, so the brackets need to be escaped separately, inside the single quotes, to not have grep interpret them as special.
Using grep -F or fgrep doesn't use regular expressions: everything to grep on is taken as a single string pattern. The single quotes would still be necessary to prevent the shell from interpreting the brackets specially.

Linux SED command syntax with escapes [duplicate]

This question already has answers here:
How to insert strings containing slashes with sed? [duplicate]
(11 answers)
Closed 6 years ago.
I am trying to replace a script call with a script call from a sub directory.
For example, originally I had ./output.sh in my script to call the output.sh script in the current directory.
I want to replace ./output.sh with ../output.sh so that it calls output.sh in the parent directory.
I tried
sed -i -e 's/../\output.sh/./\output.sh/g' scriptName.sh
This returns with
char 17: unknown option to 's'
Any help with the sed escape character syntax would be great.
Sed is bad at this; you'll risk turning an already existing ../output.sh into .../output.sh if you're not careful.
This is the best sed can do:
sed -i 's#output\.sh#../$#g' scriptName.sh
(I'm using # in place of / so that there are no forward slashes to escape. Sed accepts any punctuation character in place of forward slash.)
Note that this will convert ../output.sh to ../../output.sh but at least it doesn't create that triple-dot error.
Instead, try perl:
perl -pie 's#(?<!\.\./)(output\.sh\b)#../$1#g' scriptName.sh
This uses a negative look-behind to ensure it doesn't traverse to the parent's parent. It also allows using \b to denote a word break just in case you have something like output.shelf somewhere.
This would do the trick. Substitutes every appearance of ./output.sh for ../output.sh :
sed 's/\.\/output\.sh/\.\.\/output\.sh/g' scriptName.sh
The escape character is \. You should use it to escape:
Every dot .. The dot is used as any character in regex.
Every slash /. The slash character is used as delimiter between regex on the scommand.
The slash character is special in sed's s command if you formulate it as s/something/replacement/flags, so the slashes in your file paths cause the error. Fortunately, you can use any other character right after s, for example s#something#replacement#flags. So, replacing the command with s#\./output.sh#../output.sh#g should do the trick.
Note two additional changes: you have to escape the dot in first expression since it's also a special character in regex and you also got reversed order of search expression and replacement (thanks charli for noticing this). You don't need the backslashes before o characters, either.
Alternatively, you can use / after s but escape the literal slashes you want to replace by preceding them with backslashes: s/\.\/output.sh/..\/\output.sh/g. It seems in your code you tried to use this solution but put the backslashes after instead of before the slashes.

Pass quoted arguments to shell script and maintain quoting [duplicate]

This question already has answers here:
How do I pass on script arguments that contain quotes/spaces?
(2 answers)
Closed 2 years ago.
I'm attempting to re-use parameters sent to my script as parameters for a command I execute within my script. See example below where I execute mailx.
bash
$./myscript.sh "My quoted Argument"
myscript.sh
mailx -s $1
This ends up being executed as: mailx -s My Quoted Argument.
I tried "$1", but my quotes are thrown away. (Incorrect statement, read answer below)
I tried ""$1"" but my quotes are thrown away.
I tried to do '$1' but that's strong quoting so $1 never gets interpreted.
I realize I can do $#, but that gives me every param.
.... you get the picture
Any help would be appreciated!
mailx -s "$1" correctly passes the value of $1 to mailx as-is, embedded spaces and all.
In the case at hand, this means that My Quoted Argument is passed as a single, literal argument to mailx, which is probably your intent.
In a shell command line, quotes around string literals are syntactic elements demarcating argument boundaries that are removed by the shell in the process of parsing the command line (a process called quote removal).
If you really wanted to pass embedded double-quotes (which would be unusual), you have 2 options:
either: embed the quotes on invocation ./myscript.sh "\"My quoted Argument\""
or: embed the quotes inside myscript.sh: mailx -s "\"$1\""
You may just put escaped quotes around $1 in your script
mailx -s \"$1\"
Can you try passing the argument like this
$./myscript.sh \"My quoted Argument\"?

How to echo "$x_$y" in Bash script?

It is very interesting that if you intend to display 0_1 with Bash using the code
x=0
y=1
echo "$x_$y"
then it will only display
1
I tried echo "$x\_$y" and it doesn't work.
How can I echo the form $x_$y? I'm going to use it on a file name string.
Because variable names are allowed to have underscores in them, the command:
echo "$x_$y"
is trying to echo ${x_} (which is probably empty in your case) followed by ${y}. The reason for this is because parameter expansion is a greedy operation - it will take as many legal characters as possible after the $ to form a variable name.
The relevant part of the bash manpage states:
The $ character introduces parameter expansion, command substitution, or arithmetic expansion.
The parameter name or symbol to be expanded may be enclosed in braces, which are optional but serve to protect the variable to be expanded from characters immediately following it which could be interpreted as part of the name.
When braces are used, the matching ending brace is the first } not escaped by a backslash or within a quoted string, and not within an embedded arithmetic expansion, command substitution, or parameter expansion.
Hence, the solution is to ensure that the _ is not treated as part of the first variable, which can be done with:
echo "${x}_${y}"
I tend to do all my bash variables like this, even standalone ones like:
echo "${x}"
since it's more explicit, and I've been bitten so many times in the past :-)
This way:
$ echo "${x}_${y}"
0_1
wrap it in curly braces:
echo "${x}_${y}"
Just to buck the trend, you can also do this:
echo $x'_'$y
You can have quoted and unquoted parts next to each other with no space between. And since ' isn't a legal character for a variable name, bash will substitute only $x. :)

What's the difference between -> result=$(ls -l) (or) -> result=`ls -l`

I'v run both commands and they both seem to do the same thing, is this true or is there something happening I'm not seeing?
These two appear to do the same thing:
result=$(ls -l)
result=`ls -l`
Please check out
http://nixcraft.com/shell-scripting/13288-loop-input-backticks-vs-differences.html#post19804
for a nice explanation of this case.
The bash man page says the following, under Command Substitution.
When the old-style backquote form of
substitution is used, backslash
retains its literal meaning except
when followed by $, `, or . The
first backquote not preceded by a
backslash terminates the command
sub-stitution. When using the
$(command) form, all characters
between the parentheses make up the
command; none are treated specially.
Command substitutions may be nested.
To nest when using the backquoted
form, escape the inner backquotes with
backslashes.
Online copies of the sh man page:
bash
osx
free bsd

Resources