Creating SH function: 'defined_empty'

This works!
Code:
# var exists
if [ "${var-NON_EXISTING}" != 'NON_EXISTING' ]; then
    # and is empty
    [ ! "$var" ] && echo "Var \$var exists and is empty"
fi

Problem is, when I wana put it, in a function, which takes one arg, that is a name of a variable, to be checked.
This part of code, inside a function, always fails:
Code:
 ... "${$@-NON_EXISTING}" ...
As well as:
Code:
 ... "${"$@"-NON_EXISTING}" ...
Code:
 ... "${`echo $@`-NON_EXISTING}" ...
Code:
 ... "${"`echo $@`"-NON_EXISTING}" ...
Anyone?
 
To test for non-existing (empty) variables I usually use something like:

Code:
if [ x${var} = "x" ]
or
Code:
if [ x${var} != "x" ]
depending on how you frame your condition, of course.
 
Or something like

Code:
check-isset() {
  if [ -z "$1" ]; then
    return 1
  else
    return 0
  fi
}

check-isset $foo

I have to ask though, since you'll have to use check-isset inside of an if block anyway, why not just do:

Code:
if [ -z "$foo" ]; then
  echo "foo is not set"
fi
 
Guys!
2 conditions have to be met, for function to return 'true' (0)
1) Variable must exist (defined)
AND
2) Variable mustn't have any value -> NULL string (empty) -> var=

Anything else, returns 'false'.

Code:
# var exists
if [ "${var-NON_EXISTING}" != 'NON_EXISTING' ]; then
    # and is empty
    [ ! "$var" ] && echo "Var \$var exists and is empty"
fi
... achieves this!

Problem is putting it, inside of a function, as I need variable variable, for this, as var's name is passed to function to check is it defined AND empty.

ATM I've figured I can use eval to deal with variable variables
 
Does using $1 (instead of $var) inside the function work?

When the function is called as defined_empty $myvar, $myvar is passed in as the first positional argument, aka $1.

Although I think that passes a copy of $myvar, and not a reference to it, so you are testing whether or not $1 is defined/empty, and not $myvar.
 
Seeker said:
Guys!
2 conditions have to be met, for function to return 'true' (0)
1) Variable must exist (defined)
AND
2) Variable mustn't have any value -> NULL string (empty) -> var=

I guess I'll step back and ask, why are you doing this? I've been shell programming a long time and have never needed to know this.
 
Seeker said:
Code:
# var exists
if [ "${var-NON_EXISTING}" != 'NON_EXISTING' ]; then
    # and is empty
    [ ! "$var" ] && echo "Var \$var exists and is empty"
fi

You have a bug in your code if this is what you are using. It should be:

Code:
if [ "${var:-NON_EXISTING}" != 'NON_EXISTING' ]; then
    [ -z "$var" ] && echo 'Var $var exists and is empty'
fi

Which doesn't work by the way. I tested it with an unset variable, a variable existent but empty, and a set variable; it never prints anything.

As far as I know, there is no way to detect a variable exists short of doing something like:

Code:
if set | grep -q '^var=$'; then
    echo 'Var $var exists and is empty'
fi

But again, I would still ask what you are trying to accomplish.
 
You've declared a bug in my code, just by looking at it and without an attempt, to test it.
Then, you've just edited it and then tested it, for a first time.
In that case, I completely agree, with you:
... Which doesn't work by the way. I tested it with an unset variable, a variable existent but empty, and a set variable; it never prints anything.
And reason for that is, that your "fix", injected bugs in my code.
;)

So, if you test my unedited code, you'll see that only:
Code:
var=
will indeed produce output, while
Code:
#var=
and
Code:
var=4657
won't output anything.

Colon colored in red is your bug, which makes a major difference here:
Code:
if [ "${var[color="Red"][B]:[/B][/color]-NON_EXISTING}" != 'NON_EXISTING' ]; then
Symbol - checks only for undefined/unset vars, but once you add:
Symbol : then you are additionally checking for null value.


Anyway, you've asked, why am I doing this.
I need it for use in in_sum function, which checks if script is executing in a single user mode and it does that by checking $HOST variable (defined and empty).
I also have a script which always setups my SUM, just a way I like it and of all env vars, only $HOST remains intact. (i.e; HOME doesn't exists in SUM, but my script sets it afterwards, etc ...)

Once I hit ctrl+d, to enter multi user mode or reboot, then $HOST variable becomes non empty.
 
You're right about the hyphen thing. It's completely undocumented for both sh and bash. Since I was going off of the manpages, I figured you meant :- since it's sorta similar. Silly me using the documentation.

Personally, I'd probably use the set method described as it gives you both in a single statement at the expense of a single fork.
 
Seeker said:
I need it for use in in_sum function, which checks if script is executing in a single user mode and it does that by checking $HOST variable (defined and empty).

Seems like there would be an easier way to check that, like a sysctl or even just
Code:
if pgrep -q getty ; then
  echo "multi-user"
else
  echo "single user"
fi

Could probably use a lot of ordinary processes instead of getty, just the first thing that came to mind.
 
Yes, but my script starts up a lot of processes in SUM, so I can't rely on that.

@gordon - Yep! Your code is shorter and simpler.
But this is a mission critical function, so it must be as independent as possible(depends on itself -> /bin/sh), as SUM is associated with bad things that happened to sys, so ask god what is damaged/available and what isn't.
 
Seeker said:
@gordon - Yep! Your code is shorter and simpler.
But this is a mission critical function, so it must be as independent as possible(depends on itself -> /bin/sh), as SUM is associated with bad things that happened to sys, so ask god what is damaged/available and what isn't.

If you are that concerned about it, how about some code that requires no forks:
Code:
defined_empty() {
set | while read line
do
  case $line in
  "$1=") echo "\$$1 is set and empty" ;;
  esac
done
}

And then to run it:
Code:
# var=
# defined_empty var
$var is set and empty
 
Hey, thx gordon!
Here is a little fix:
Code:
defined_empty() {
set | while read line
do
  case $line in
  "$1=[color="Red"][B][SIZE="3"]''[/SIZE][/B][/color]") echo "\$$1 is set and empty in line $line";;
  esac
done
}
 
Code based on
Code:
set | while read ...
is probably both slow and unreliable. It forks twice and processes a lot of data that is not relevant. Also, it may give wrong answers if there is a variable containing <newline>var=<newline>.

Instead, try
Code:
[ ${var+set} ] && ! [ ${var:+setwithval} ]

If you want this in a function that is passed the variable name, for some reason, you will need to use eval.

The colon for the +-=? expansions is documented below them in sh(1):
In the parameter expansions shown previously, use of the colon in the
format results in a test for a parameter that is unset or null; omission
of the colon results in a test for a parameter that is only unset.
 
Back
Top