Unix Commands interpretation - unix

what's the meaning of the following notation in Unix ?
:- or :=
what does the following means
if [ ${path:=0} -eq 1 ]
if [ ${path:-0} -eq 1 ]

The : is a parameter expansion, so if for instance $path is not set, it will fall back to 0 in your example code.
Using a hyphen :- will use the value, and using := will assign the value.
Additional info prompted by comment:
In your example, you are using a variable called $path, so using the := will go like this: if $path is not set, set $path to the value (0 in your case). Any time you use $path afterwards it would be set to your value, 0.
Using :- will simply just use the default value given (again, 0 in your case) and NOT assign it to $path. Any uses of $path afterwards still be not set.

Related

Error "a name is not defined" when using a variable in expression

I am trying to test against multiple environments with a single test case using the passing in of a variable from the command line. Using the following command line:
robot --variable TESTENV:prod advertisingdisclosure_Page.robot
I need to test the value of TESTENV and depending on the value passed in set a different variable, specifically a URL, to the appropriate value. With the following code in the first keyword section of the test case I get an error:
IF ${TESTENV} == "uat"
$(MAIN_URL)= Set Variable ${env_data['uat_url']}
ELSE IF ${TESTENV} == "dev"
${MAIN_URL}= Set Variable ${env_data['dev_url']}
ELSE IF ${TESTENV} == "prod"
${MAIN_URL}= Set Variable ${env_data["prod_url"]}
ELSE
Fail "No URL specified"
END
I get the following error:
Evaluating expression 'prod' failed: NameError: name 'prod' is not defined nor importable as module
The examples I have found show how to use the Global Variable directly, but not how to evaluate it for a specific value.
Help.
Jeff
You need to put quotes around the variable name - otherwise the framework just puts its value in, and passes that expression to python.
Thus it becomes prod == '"uat", and py rightfully complains there is no defined variable prod.
The fix is simple - just surround the usage in quotes, and after substitution this will become a string comparison:
"${TESTENV}" == "uat"
Alternatively you can use another syntax - no curly brackets, which tells RF to use/pass the variable itself, not its value, and then it will be a defined one for python:
$TESTENV == "uat"

zsh : Testing the existence of a variable via indirect reference

If I want to know, whether variable v exists in zsh, I can use ${+v}. Example:
u=xxx
v=
print ${+u} ${+v} ${+w}
outputs 1 1 0.
If I want to access the content of a variable, where I have the NAME of it stored in variable v, I can do it with ${(P)v}. Example:
a=xxx
b=a
print ${(P)b}
outputs xxx.
Now I would like to combine the two: Testing whether a variable exists, but the name of the variable is stored in another variable. How can I do this? Example:
r=XXX
p=r
q=s
Here is my approach which does NOT work:
print ${+${(P)p}} # Expect 1, because $p is r and r exists.
print ${+${(P)q}} # Expect 0, because $q is s and s does not exist
However, I get the error message zsh: bad substitution.
Is there a way I can achieve my goal without reverting to eval?
print ${(P)+p}
print ${(P)+q}
The opening parenthesis of of a Parameter Expansion Flag needs to follow immediately after the opening brace. Also, it is not necessary to explicitly substitute p or q as (P) takes care of that. Nevertheless, ${(P)+${p}} and ${(P)+${q}} would also work.

Octave: I cannot change the value of a global variable after clearing it

I have defined a global variable global x=-2. Once created, global variables cannot be reassigned, i.e., x=7 will not change the -2 value of x. For this reason I clear the variable.
>> clear x
I check that the variable does not exist any more.
>> exist("x")
ans = 0
But when I create the global variable again with a new value, for example, global x=7 I get the global variable in the old value.
>> global x=7
>> x
x = -2
Why is this happening? Is the variable x not really deleted?
What you see is expected behaviour. It looks weird but consider the following example:
global x = 5;
function say_x ()
global x = 3;
disp (x);
endfunction
say_x ();
x = 7;
say_x ();
Which returns:
5
7
Note that you need declare x within functions to access the global variable. Also note that assigning to it the value of 3 does not work. The reason is that lines such as persistent x = 3 or global x = 3 are only evaluated the first time. This means that when you call say_x(), x already has a value so it never assigns to it the value of 3 (the right hand side never even gets evaluated).
Now; on to your actual issue which is all of this happening in the main/base namespace/symbol table, mixed up with what clear() is supposed to do. You are running this:
global x = 1;
clear x;
global x = 2;
x # you are surprised that x is 1 instead of 2
First, note that clear() does not actually clears the values of the variables. It will remove their names from the symbol table. Note the help text from clear():
-- Command: clear [options] pattern ...
Delete the names matching the given patterns from the symbol table.
With "normal" variables, the names won't be anywhere else and you will effectively remove their value. But that's not true with global variables. Their values will remain somewhere, ready to be made accessible the next time a global variable with their name gets defined.
What is happening when you try to define x again, is that the name already exists in the symbol table of global variables. So you are bringing it back to the current symbol table (just like what happens inside a function) and the right hand side (= 2) never gets evaluated.
As you already found, to actually remove names from the global symbol table, you need to use clear -global (as it is documented on the help text of clear).
We need to use the option -global to effectively delete the global variable: clear -global x
Example:
>> global x=-2
>> clear -global x
>> exist("x")
ans = 0
>> global x=7
>> x
x = 7
This must be a bug in Octave, because clear command alone seems to work fine clearing the global variable: no error message, and the "exist" check outputs the expected.
(Hope it helps, it took me some minutes to find the solution ;))

Printing unexpanded recursive variables in gnu make

Is there a way to print the unexpanded definition of a recursive variable? I have a complicated build system, and a user can set some values. I'd like to echo the user definition to another file, for later use.
For example,
externals = $(HOME)/externals
all:
echo $(externals)
doesn't work, because it echos using the current definition of HOME. I'd like it to echo
the literal string $(HOME)/externals without expanding $(HOME).
The value function is probably what you want here.
8.8 The value Function
The value function provides a way for you to use the value of a variable without having it expanded. Please note that this does not undo expansions which have already occurred; for example if you create a simply expanded variable its value is expanded during the definition; in that case the value function will return the same result as using the variable directly.
The syntax of the value function is:
$(value variable)
Note that variable is the name of a variable, not a reference to that variable. Therefore you would not normally use a ā€˜$ā€™ or parentheses when writing it. (You can, however, use a variable reference in the name if you want the name not to be a constant.)
The result of this function is a string containing the value of variable, without any expansion occurring. For example, in this makefile:
FOO = $PATH
all:
#echo $(FOO)
#echo $(value FOO)
The first output line would be ATH, since the ā€œ$Pā€ would be expanded as a make variable, while the second output line would be the current value of your $PATH environment variable, since the value function avoided the expansion.
The value function is most often used in conjunction with the eval function (see Eval Function).
Though in addition to this you are going to need to use single quotes on that echo line or the shell will expand things on you.
$ cat Makefile
externals = $(HOME)/externals
all:
echo $(externals)
allv:
echo $(value externals)
allvq:
echo '$(value externals)'
$ make all
echo /home/user/externals
/home/user/externals
$ make allv
echo $(HOME)/externals
/bin/sh: HOME: command not found
/externals
$ make allvq
echo '$(HOME)/externals'
$(HOME)/externals

TCL global stumping me

I have a script where I am doing what appears to be the exact same thing, but it works in that one and not this one. I'm hoping that a few more pairs of eyes will be able to help me find out the issue, I've already spent an hour and a half on it.
I have a proc that edits the global var, it's more complex that this but I'll use this for simplicity's sake:
proc myCustomProc { var } {
global __myGlobal
set __myGlobal [ expr $__myGlobal + 1 ]
}
I have defined a variable globally in my "main" proc:
proc FOO {} {
global __myGlobal
...
...
myCustomProc 5
puts $__myGlobal
Then I get can't read "__myGlobal": no such variable
I have the exact code with a different varname working in a different script, so I'm stumped. Obviously it's NOT identical, I just cannot find the issue.
Edit: both procs are in the same .tcl file
You can't read from a variable that is unset, and that's true whether that variable is global or not. Thus, in the code:
set __myGlobal [ expr $__myGlobal + 1 ]
It first reads the value from the global variable, then adds one to that value, then writes the result back to the global variable. (Actually, it is interpreting the contents of the variable as an expression fragment, which I'd lay good money on being something you don't want as it is slow and unsafe; put the whole expression in braces please.)
For adding one to an integer (and from Tcl 8.5 onwards) you should just use the incr command instead, as that interprets a non-existent value as if it was zero:
incr __myGlobal
But if you're doing something more complex (or working in 8.4 or before), you should instead put a check with info exists like this in front:
if {![info exists __myGlobal]} {
set __myGlobal "the default value"; # Or whatever default you want
}
You could also use a more complex expression like this:
set __myGlobal [expr {[info exists __myGlobal] ? $__myGlobal+1 : 1}]
But I usually try to avoid the ternary operator; it's often not that readable.
The short answer is, you are using $__myGlobal in the expr command before it has been set.

Resources