I am writing a shell script where I am setting few variables, whose value is the output of commands.
The errors I get are:
$ $tag_name="proddeploy-$(date +"%Y%m%d_%H%M")"
-bash: =proddeploy-20141003_0500: command not found
now, I did read other similar questions and based on it, I tried various things:
spliting command into two calls
$ $deploy_date=date +"%Y%m%d_%H%M"
bash: =date: command not found
$ $tag_name="proddeploy-$deploy_date"
bash: proddeploy- command not found
tried using backticks
$ $tag_name=`proddeploy-$(date +"%Y%m%d_%H%M")`
bash: proddeploy-20141003_1734: command not found
bash: =: command not found
tried using $()
$ $tag_name=$(proddeploy-$(date +"%Y%m%d_%H%M"))
bash: proddeploy-20141003_1735: command not found
bash: =: command not found
But in every case the command output is getting executed. how do I make it to stop executing command output and just store as a variable? I need this to work on ZSH and BASH.
You define variables with var=string or var=$(command).
So you have to remove the leading $ and any other signs around =:
tag_name="proddeploy-$(date +"%Y%m%d_%H%M")"
deploy_date=$(date +"%Y%m%d_%H%M")
^^ ^
From Command substitution:
The second form `COMMAND` is more or less obsolete for Bash, since it
has some trouble with nesting ("inner" backticks need to be escaped)
and escaping characters. Use $(COMMAND), it's also POSIX!
Also, $() allows you to nest, which may be handy.
The accepted answer shows corrected code, but does not clarify that one of your problems is accessing a variable (using $) while assigning it, which is illegal.
For example:
$foo=4
should be
foo=4
See the difference? foo is being assigned, so you should not use $foo, which is not foo but the value of foo.
Related
I would expect the second line to say foo instead of command not found:
$ alias foo="echo bac" ; foo;
-bash: foo: command not found
$ foo
bac
$
Why won't the second line say foo? Tested with the following shells, same behavior:
bash 3.2.5
zsh 5.0.8
dash 0.5.9
busybox 1.25.0
The behaviour you're seeing is described in the Bash Reference Manual (emphasis mine):
The rules concerning the definition and use of aliases are somewhat confusing. Bash always reads at least one complete line of input before executing any of the commands on that line. Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias.
Presumably the other shells also behave in this way.
To set and use alias in the same line in bash, you can use:
eval $'alias df5=df\ndf5 -h'
(credits: Hauke Laging's workaround + Kusalananda's workaround).
Explanation of the command:
Since "an alias definition appearing on the same line as another command does not take effect until the next line of input is read" according to the bash manual as Tom Fenech's pointed out, we use eval and place a new line between the alias definition and its use.
From Kusalananda's workaround:
"The $'...' is a "C string", and bash would expand the \n within it to a literal newline before passing it to eval.
I always get a bad substitution error when I use Parameter Transformation in a script
#!/usr/bin/env bash
abc=abc
echo ${abc#U}
result
line 3: ${abc#U}: bad substitution
However, it works fine in interactive mode
> abc=abc
> echo ${abc#U}
ABC
I'm aware of the
Bash: How to use operator parameter expansion ${parameter#operator}?
question but there is no answer.
How can I use parameter transformation in a script?
Need bash version 5.1 or greater
I saw an expression a=($(cat)) which I am not able to understand from it's working mechanism perspective.
Functionally it takes input from the standard input and assigns it to variable a (which forms an array).
My understanding is , when shell executes the inner parenthesese it executes the cat command which brings the standard input, and when you type a few lines on the standard input and press CTRL+D it returns the lines to the outer parenthesese which then assign the lines to an array a.
My question is why this expression gives error when I remove the $ and write it as a=((cat)).
It is because $(..) is a command substitution syntax to run commands on. The cat in your example run in a sub-shell under this construct. Without it the command cat and ( are interpreted literally which the shell does not like
From the bash(1) - Linux man page
Command Substitution
Command substitution allows the output of a command to replace the command name. There are two forms:
$(command) (or) command
Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.
The arithmetic operator in bash is $((..)) which is not the syntax you are using in your example
I am confused by how to use variables in Bash. Please see the following example. I am not able to figure out why Bash isn't able to recognize the variable within (). Can anybody please help me understand what is going on.
$echo $SHELL
/bin/bash
$export TestC=/Users
$echo $TestC
/Users
$export TestD=$TestC/ABCD
$echo $TestD
/Users/ABCD
$export TestD=$(TestC)/ABCD
-bash: TestC: command not found
Thanks for your help
When referencing a bash variable you either use $ then the name, as in $TestC or you can put braces around the name like ${TestC}.
$(...) is a subshell syntax called command substitution that will execute the command inside the parens then "return" the stdout of that command.
Read all about parameter/variable expansion here, which also shows a lot of the extra things you can do with the parameter expansion when using braces.
I would expect the second line to say foo instead of command not found:
$ alias foo="echo bac" ; foo;
-bash: foo: command not found
$ foo
bac
$
Why won't the second line say foo? Tested with the following shells, same behavior:
bash 3.2.5
zsh 5.0.8
dash 0.5.9
busybox 1.25.0
The behaviour you're seeing is described in the Bash Reference Manual (emphasis mine):
The rules concerning the definition and use of aliases are somewhat confusing. Bash always reads at least one complete line of input before executing any of the commands on that line. Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias.
Presumably the other shells also behave in this way.
To set and use alias in the same line in bash, you can use:
eval $'alias df5=df\ndf5 -h'
(credits: Hauke Laging's workaround + Kusalananda's workaround).
Explanation of the command:
Since "an alias definition appearing on the same line as another command does not take effect until the next line of input is read" according to the bash manual as Tom Fenech's pointed out, we use eval and place a new line between the alias definition and its use.
From Kusalananda's workaround:
"The $'...' is a "C string", and bash would expand the \n within it to a literal newline before passing it to eval.