Difference between Groovy String variable replacement - string

When looking at examples of variable substitution in GStrings, I have noticed two difference syntaxes. This can be seen here: Groovy Templates
This has the example:
def text = 'Dear "$firstname $lastname",\nSo nice to meet you in <% print city %>.\nSee you in ${month},\n${signed}'
It looks like ${variable} is used more commonly when you have an expression, but $variable is used when you just have a single variable, but even here they mix it with $firstname and ${month}. Is there a reason to do it one way or another when you have a single variable and not an expression, or does it not matter?

It doesn't matter...
As you say, if you have an expression like "${name.toUpperCase()}", "${number}th" or "${list[0]}", then it has to be inside braces, but both "${name}" and "$name" are the same.
Indeed, so long as it's simple property access you can omit the braces, ie: "Hello $person.username"
It could be said that adding the braces can make your string templates easier to read, but that's a personal preference thing.

Related

Adding multiple user inputs into one variable in Bash

I am fairly new to unix bash scripting and need to know if this is possible. I want to ask user for their input multiple times and then store that input in to one variable.
userinputs= #nothing at the start
read string
<code to add $string to $userinputs>
read string
<code to add $string to $userinputs> #this should add this input along with the other input
so if the user enters "abc" when asked first time, it add's "abc" in $userinputs
then when asked again for the input and the user enters "123" the script should store it in the same $userinputs
this would make the $userinput=abc123
The usual way to concat two strings in Bash is:
new_string="$string1$string2"
{} are needed around the variable name only if we have a literal string that can obstruct the variable expansion:
new_string="${string1}literal$string2"
rather than
new_string="$string1literal$string2"
You can also use the += operator:
userinputs=
read string
userinputs+="$string"
read string
userinputs+="$string"
Double quoting $string is optional in this case.
See also:
How to concatenate string variables in Bash?
You can concatentate variables and store multiple strings in the same one like so:
foo=abc
echo $foo # prints 'abc'
bar=123
foo="${foo}${bar}"
echo $foo # prints 'abc123'
You can use the other variables, or the same variable, when assigning to a variable, e.g. a="${a}123${b}". See this question for more info.
You don't have to quote the strings you're assigning to, or do the ${var} syntax, but learning when to quote and not to quote is a surprisingly nuanced art, so it's often better to be safe than sorry, and the "${var}" syntax in double quotes is usually the safest approach (see any of these links for more than you ever wanted to know: 1 2 3).
Anyway, you should read into a temporary variable (read, by default, reads into $REPLY) and concatentate that onto your main variable, like so:
allinput=
read # captures user input into $REPLY
allinput="${REPLY}"
read
allinput="${allinput}${REPLY}"
Beware that the read command behaves very differently depending on supplied switches and the value of the IFS global variable, especially in the face of unusual input with special characters. A common "just do what I mean" choice is to empty out IFS via IFS= and use read -r to capture input. See the read builtin documentation for more info.

erb - How to substitute a string (gsub) which contains legit backslashes?

I had the following problem with erb in combination with Puppet, Hiera and templates:
Via Hiera I got the following strings as variables:
First the variable example in an array (data[example])
something with _VARIABLE_ in it
and variable example_information with
some kind of \1 and maybe also a \2
Now I wanted to substitute _VARIABLE_ in a Puppet template with the second string which contains a legit backslash () in it. So I did it like this:
result=data['example'].gsub('_VARIABLE_', #example_information)
So I took example out of an array and filled the placeholder with #example_information.
The result was as follows:
something with some kind of and maybe also a in it
There was no backslash as gsub interpreted them as backreferences. So how can I solve my issue to preserve my backslashes without double escape them in the Hiera file? I need the Hiera variable further in the code without double escaped backslashes.
I now made this to solve that specific problem as follows:
Variable again example
something with _VARIABLE_ in it
and variable example_information with
some kind of \1 and maybe also a \2
Code part in the template:
# we need to parse out any backslashes
info_temp=example_information.gsub('\\', '__BACKSLASH__')
# now we substitute the variables with real data (but w/o backslashes)
result_temp=data['example'].gsub(/__ITEM_NAME__/, info_temp)
# now we put together the real string with backslashes again as before
result=result_temp.gsub('__BACKSLASH__', '\\')
Now the result looks as follows:
something with some kind of \1 and maybe also a \2 in it
Note
Maybe there is a better way to do it but on my research I didn't stumble upon a better solution so please add comments if you know a better way to do it.

Can I use double quotes in Chef attribute declaration?

I have inherited a cookbook that sets some attributes in the ./attributes/default.rb file as per normal.
However, we have a problem with one of the lines is, which is:
default["obscured"]["mysql"] = "#{node['jboss']['jboss_home']}/modules/com/mysql/jdbc/main"
When run, it write this into the node as:
{}/com/mysql/jdbc/main
I can confirm that the node['jboss']['jboss_home'] attribute exists and has correct values.
So, I cannot see any problem with the above, except that every other declaration of this type in our cookbooks has single quotes on the attribute to be set (i.e. left side), not double quotes. I haven't heard this of as being an issue before, but I am pretty new to chef.
Is there any rule that says they must be single quotes?
The answer is that there is no rule.
Using double-quotes in something like this is completely fine:
default["obscured"]["mysql"] = blah blah
The reason I know that is that I just found one being set, with double quotes, that actually works. :-)
What you have there is fine, how are you confirming the value of node['jboss']['jboss_home'] and how are you using it in the template?
In Ruby single and double quoted literals both become Strings but single quotes are relatively literal while double quotes allow backslash escapes and #{} interpolation.
You are most likely hitting the derived attributes problem:
https://coderanger.net/derived-attributes/
The attribute code in your cookbook is getting parsed before the jboss_home attribute is being set. One way or another the solution is to move the interpolation into recipe code.
You could just use a plain old ruby variable instead of the attribute you are trying to construct -- particularly if nothing else in your system ever sets that attribute.
You also should be able to delete the declaration from your attributes file and use this in recipe code as well:
node.default_unless["obscured"]["mysql"] =
"#{node['jboss']['jboss_home']}/modules/com/mysql/jdbc/main"
Although you need to place that statement early in your run_list, before you ever use node["obscured"]["mysql"] as an argument to any resource.

A variable of which a part is variable

I have variables that look something like this:
$INFOMonday
$INFOTuesday
In my Bash script, I would like to use the value of todays variable, so to say. I extracted the day with:
dayofweek=$(date --date=${dateinfile#?_} "+%A")
What I need help with, is doing the following:
echo $INFO$dayofweek
Is there any way of adding a variable as part of a variables name? For example, if it's monday, the echo would return the value of $INFOMonday.
The old-style way of doing this is with the indirection operator ${!variable}:
dayofweek=$(date...)
var=INFO$dayofweek
echo ${!var}
Note that in ${!var}, var must be a variable-name, not a string expression or other type of substitution. It's a little clunky.
The newer way of doing it would be with an associative array.

Concatenate string literals

I've seen a couple posts for this, like this one, but none are helping me in my particular situation.
scriptsPath="/var/db/gbi/scripts/"
echo "$scriptsPathawesome.csv";
I would expect this to echo /var/db/gbi/scripts/awesome.csv
Instead I get .csv
Seems like it thinks I'm trying to reference a variable named $scriptsPathawesome. How can I concatenate the $scriptsPath variable to the "awesome.csv" string literal?
You need to surround your variable with curly braces like so:
scriptsPath="/var/db/gbi/scripts/"
echo "${scriptsPath}awesome.csv";

Resources