Can someone explain to me what is the difference, in Korn shell, between:
ANOTHER_VAR=${SOME_VAR}
and
ANOTHER_VAR=$SOME_VAR
I came across these types of declaration and can't see what the difference is.
One has two brace characters around the name and the other doesn't; otherwise, in this context, there is no difference.
However, if you had:
ONE_VAR="$TWO_VAR_$THREE_VAR"
UNO_VAR="${TWO_VAR}_${THREE_VAR}"
then the values in $ONE_VAR and $UNO_VAR will be different unless both $TWO_VAR and $TWO_VAR_ exist and $TWO_VAR_ holds the value that is stored in $TWO_VAR plus a trailing underscore (where $TWO_VAR could be an empty string, or undefined, as long as $TWO_VAR_ holds just an underscore).
Thanks to William Pursell for pointing out a minor inaccuracy in the previous version.
There are many contexts where you must use the braces, such as:
UNE_VAR=${YET_ANOTHER_VAR:-"default setting"}
Related
In a situation like this for example:
[% $create_port %]
or [list [% $RTL_LIST %]]
I realized it had to do with the brackets, but what confuses me is that sometimes it is used with the brackets and variable followed, and sometimes you have brackets with variables inside without the %.
So i'm not sure what it is used for.
Any help is appreciated.
% is not a metacharacter in the Tcl language core, but it still has a few meanings in Tcl. In particular, it's the modulus operator in expr and a substitution field specifier in format, scan, clock format and clock scan. (It's also the default prompt character, and I have a trivial pass-through % command in my ~/.tclshrc to make cut-n-pasting code easier, but nobody else in the world needs to follow my lead there!)
But the code you have written does not appear to be any of those (because it would be a syntax error in all of the commands I've mentioned). It looks like it is some sort of directive processing scheme (with the special sequences being [% and %], with the brackets) though not one I recognise such as doctools or rivet. Because a program that embeds a Tcl interpreter could do an arbitrary transformation to scripts before executing them, it's extremely difficult to guess what it might really be.
I could use some suggestions, this probably isn't the most elegant way to do this but it's what came to mind. Let me add a couple snippets for clarity.
week1="01-\(04\|05\|06\|07\|08\|09\|10\)-2016"
week2="01-\(11\|12\|13\|14\|15\|16\|17\)-2016"
week3="01-\(18\|19\|20\|21\|22\|23\|24\)-2016"
week4="01-\(25\|26\|27\|28\|29\|30\|31\)-2016"
week5="02-\(01\|02\|03\|04\|05\|06\|07\)-2016"
I have a text file that has dates in each line, for example
293232343;01-02-2016;blah;more blah
234872348;02-01-2016;blah;extra blah
I am trying to create a loop so I can grab different data depending on the calendar week.
current_week=`date +%W`
for (( c=1; c<=$current_week; c++ ))
do
sort -k2 archive.txt|tr "\\t" ";"|grep $week$c|while read line; do
My problem is that $week$c doesn't actually translate to $week1, $week2, etc. Any easy solutions here? Thanks in advance.
From man bash:
If the first character of parameter is an exclamation point, a level
of
variable indirection is introduced. Bash uses the value of the vari-
able formed from the rest of parameter as the name of the variable;
this variable is then expanded and that value is used in the rest of
the substitution, rather than the value of parameter itself. This is
known as indirect expansion. The exceptions to this are the expansions
of ${!prefix*} and ${!name[#]} described below. The exclamation point
must immediately follow the left brace in order to introduce indirec-
tion.
Then, what you need is
var="week$c"
... grep "${!var}" ...
From https://stackoverflow.com/a/10820494/1764881, I know that the standard way of doing it seems to be:
var="SAMPLE$i"
echo ${!var}
But, I can't seem to do any of these following forms. They all failed:
echo ${!SAMPLE$i}
echo ${!"SAMPLE$i"}
I read the bash man page, but I still couldn't understand. Is it true that the first form is the only form accepted?
Yes. The underlying logic is that all parameter expansions take a single, literal word as the name of the parameter to expand, and any additional operator does something to the result. ! is no exception; var is expanded as usual, but the result is expanded again.
(As an aside, even arrays follow this rule. It might seem that something like ${array[2]%foo} applies two operators to array, but really array[2] is treated as the name of a single parameter. There is a little difference, as the index is allowed to be an arbitrary arithmetic expression rather than a literal number.)
(And for completeness, I should mention the actual exceptions, ${!prefix*} and ${!name[*]}, which confusingly use the same operator ! for querying variables themselves. The first lists variable names starting with the same prefix; the second lists the keys of the named array.)
I'm looking over a script (which has been used successfully in the past) which contains the following:
node=1
while :
do
userKey=WEB_${node}_USER
userVal=`echo ${!userKey}`
I have not been able to figure out why an exclamation point would be added to a variable reference like this. What purpose does "!" serve in this context?
It's rare for me to do much scripting so if I am missing any details please let me know and I will try to provide more information. I have not been able to find this answer elsewhere.
Thanks in advance!
It's called indirect parameter expansion. Where $userKey expands to the value of the variable userKey, ${!userKey} expands to the value of the variable whose name is the value of userKey. Since usrKey has the value WEB_1_USER (given the current value of $node, ${!userKey} expands to the same result as $WEB_1_USER.
Its use is somewhat rare, since in many cases (including, it appears, here) an array WEB_USER of user names would be clearer than a set of numbered variables.
WEB_USER=(alice bob charlie)
node=1
while :
do
userVal=${WEB_USER[node]}
In bash, I thought that the only characters that retained their meta-character status inside double quotes were the dollar sign ($), the back-tick (`) and the backslash (\).
Which form is most efficient?
1)
v=''
v+='a'
v+='b'
v+='c'
2)
v2='a'` `'b'` `'c'
Assuming readability were exactly the same to you, and that's a stretch, would 1) mean creating and throwing away a few string immutables (like in Python) or act as a Java "StringBuffer" with periodical expansion of the buffer capacity? How are string concatenations handled internally in Bash?
If 2) were just as readable to you as 1), would the backticks spawn subshells and would that be more costly, even as a potential 'no-op' than what is done in 1) ?
Well, the simplest and most efficient mechanism would be option 0:
v="abc"
The first mechanism involves four assignments.
The second mechanism is bizarre (and is definitely not readable). It (nominally) runs an empty command in two sub-shells (the two ` ` parts) and concatenates the outputs (an empty string) with the three constants. If the shell simply executes the back-tick commands without noting that they're empty (and it's not unreasonable that it won't notice; it is a weird thing to try — I don't recall seeing it done in my previous 30 years of shell scripting), this is definitely vastly slower.
So, given only options (1) and (2), use option (1), but in general, use option (0) shown above.
Why would you be building up the string piecemeal like that? What's missing from your example that makes the original code sensible but the reduced code shown less sensible.
v=""
x=$(...)
v="$v$x"
y=$(...)
v="$v$y"
z=$(...)
v="$v$z"
This would make more sense, especially if you use each of $x, $y and $z later, and/or use intermediate values of $v (perhaps in the commands represented by triple dots). The concatenation notation used will work with any Bourne-shell derivative; the alternative += shell will work with fewer shells, but is probably slightly more efficient (with the emphasis on 'slightly').
The portable and straight forward method would be to use double quotes and curly brackets for variables:
VARA="beginning text ${VARB} middle text ${VARC}..."
you can even set default values for empty variables this way
VARA="${VARB:-default text} substring manipulation 1st 3 characters ${VARC:0:3}"
using the curly brackets prevents situations where there is a $VARa and you want to write ${VAR}a but end up getting the contents of ${VARa}