1

I am attempting to check if an argument is an array with the following code:

if [[ $(declare -p $1) ]] != *-a*;

Here $1 is a string with the value "123". I get the following error message from bash:

`arrays.bash: line 23: declare: 123: not found

This code works if I pass an array as an argument but not a string. I want to verify that the argument is either an array or an associative array. I have no concern with the contents at this point, I only want the type. Any ideas on how to do this?

20
  • 3
    $1 is always a string. Always. It cannot be anything else. That also means it cannot be an array. Commented Jan 29, 2023 at 0:45
  • 1
    One could pass a string with the name of an array in $1, but it's still a string. Commented Jan 29, 2023 at 0:46
  • 1
    Anyhow -- the code in your question checks what kind of variable the string in $1 refers to, with the assumption that the string is in fact a variable name; it's falling when you aren't passing a variable name at all. This is to be expected. Commented Jan 29, 2023 at 0:47
  • 1
    ...regardless, you aren't providing a minimal reproducible example showing us how you're defining the array and how you're trying to pass it; from the question I don't even know that you're using a real array at all (we get a lot of n00bs using strings that contain whitespace and calling them arrays), much less how you're attempting to pass it. Commented Jan 29, 2023 at 1:04
  • 1
    Again, we need an actual minimal reproducible example. I don't know when you say "passing c" you mean yourfunc c or yourfunc "$c" or yourfunc "${c[@]}" or something else. Runnable code is far more precise than English-language descriptions of code. Commented Jan 29, 2023 at 1:12

2 Answers 2

1

After all, why worry about the types, if you are relying on it perhaps your approach is wrong or you may need a strong-typed language

% v=1
% declare -p v
declare -- v="1"
% echo $v
1
% echo ${v[@]}
1
% v[1]=2
% declare -p v
declare -a v=([0]="1" [1]="2")
% echo ${v[@]}
1 2
Sign up to request clarification or add additional context in comments.

Comments

0

The Error In The Question

You called yourfunction "$a" instead of yourfunction a, when a=123. Don't do that: You need to pass the name of the variable, not its value.


General Solution: Bash 5.x+

Bash 5 has a new feature called parameter transformation, whereby ${parameter@operator} can perform a variety of actions; one of these is checking the type of the parameter.

myfunc() {
  [[ -v "$1" ]] || { echo "No variable named $1 exists" >&2; return 1; }
  case ${!1@a} in
    *a*) echo "Array";;
    *A*) echo "Associative array";;
    *i*) echo "Integer";;
    "")  echo "Default string";;
    *)   echo "Other/unknown flag set: ${!1@a}";;
  esac
}

Older Solution

myfunc() {
  local typedesc
  typedesc=$(declare -p "$1" 2>/dev/null) || {
    echo "No variable named $1 is set" >&2
    return 1
  }
  case $typedesc in
    "declare -a"*) echo "Array";;
    "declare -A"*) echo "Associative array";;
    "declare -i"*) echo "Integer";;
    "declare --"*) echo "Regular (default) string variable";;
    *)             echo "Other/unrecognized type";;
  esac
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.