Is there no unless in shell script?

12,071

Solution 1

First, this

[ ${myhash[$key]+abc} ]

will test if the result of the parameter expansion is empty or not. Either ${myhash[$key]} exists and expands to a string (which itself may or may not be empty), or it does not and it expands to the string "abc". Assuming you don't set myhash[$key]="", the expansion always produces a non-empty string, and so the command succeeds. As a result, ! [ ${myhash[$key]+abc} ] would always fail.

Assuming "abc" is not a valid entry in myhash, you need to actually check if the parameter expands to an actual value, or "abc" for unset keys:

if [[ ${myhash[$key]+abc} == abc ]]; then
    echo "$key does not exist in myhash"
else
    echo "myhash[$key]=${myhash[$key]}"
fi

Solution 2

The reason nothing is printed is because you check if the value is unset after setting it.

Here's what you're doing:

#!/bin/bash
key=foo

declare -A myhash                     # create associative array
myhash[$key]="1"                      # set the value
if ! [ ${myhash[$key]+abc} ]; then    # check if value is not set
     echo $key                        # if so, print key 
fi

And now you're asking "Why isn't the unset check triggering when the value is set?"

If you instead wanted to check if the key is set, you should not have inverted the existence check using !.

As for [ ${myhash[$key]+abc} ] && echo $key giving abc: command not found, I can't explain that. It would never normally happen.

That is what you would have seen if you did ${myhash[$key]+abc} && echo $key though. Are you sure you're correctly presenting the actual examples you ran, and the actual results you got

Solution 3

Easiest way to check for an index or a key in an array? shows how to check if it exists with [ ${array[key]+abc} ].

If it does, the command exits successfully, so the portion after the && gets executed (echo "exists")

You want to check if it doesn't exist. So you want your command to be executed if the [..] portion exits unsuccessfully. So use || instead of &&:

[ ${myhash[$key]+abc} ] || echo "does not exist"

&&: carry on with next command only if first succeeded

||: only carry on with next command if first did not succeed

Share:
12,071

Related videos on Youtube

olala
Author by

olala

Learning programming, computation, data analysis, so much to learn but I'm enjoying it!

Updated on June 06, 2022

Comments

  • olala
    olala about 2 years

    I tried to do the opposite of if in shell to only do something if a value in a hash doesn't exist. I've learned to create a hash in bash from here:Associative arrays in Shell scripts

    declare -A myhash
    

    I declared a simple hash:

    myhash[$key]="1"
    

    and

    [ ${myhash[$key]+abc} ]
    

    to see if myhash[$key] exist or not from here: Easiest way to check for an index or a key in an array?

    I also learned to add ! in front of an expression to do the opposite in if clause from here:How to make "if not true condition"?

    But the following expression

    if ! [ ${myhash[$key]+abc} ]; then
         echo $key
    
    fi
    

    doesn't work and no information is printed. There is no error message.

    I tried this:

    [ ${myhash[$key]+abc} ] && echo $key
    

    And got the error message:

    abc: command not found
    

    Can anyone tell me how to make it work?

    • shellter
      shellter over 10 years
      consider editing your question to include 1. Exact error message you're getting or other evidence of "it doesn't work". 2. a simple test case providing values for myhash[key]. The [ .. ] construct is documented in most systems with man test. It is expecting a command as the result of converting ${myhash[key]+abc} to a string. Good luck.