How to Create Shell Variable with Dashes

Can shell variable name include a hyphen or dash (-)?

I've never met a Bourne-style shell that allowed - in a variable name. Only ASCII letters (of either case), _ and digits are supported, and the first character must not be a digit.

If you have a program that requires an environment variable that doesn't match the shell restrictions, launch it with the env program.

env 'strange-name=some value' myprogram

Note that some shells (e.g. modern dash, mksh, zsh) remove variables whose name they don't like from the environment. (Shellshock has caused people to be more cautious about environment variable names, so restrictions are likely to become tighter over time, not more permissive.) So if you need to pass a variable whose name contains special character to a program, pass it directly, without a shell in between (env 'strange-name=some value' sh -c'…; myprogram' may or may not work).

How to create shell variable with dashes?

I've never met a Bourne-style shell that allowed - in a variable name. Only ASCII letters (of either case), _ and digits are supported, and the first character must not be a digit.

If you have a program that requires an environment variable that doesn't match the shell restrictions, launch it with the env program.

env 'strange-name=some value' myprogram

Note that some shells (e.g. modern dash, mksh, zsh) remove variables whose name they don't like from the environment. (Shellshock has caused people to be more cautious about environment variable names, so restrictions are likely to become tighter over time, not more permissive.) So if you need to pass a variable whose name contains special character to a program, pass it directly, without a shell in between (env 'strange-name=some value' sh -c'…; myprogram' may or may not work).

https://unix.stackexchange.com/questions/23659/can-shell-variable-name-include-a-hyphen-or-dash

Why can't environment variables with dashes be accessed in bash 4.1.2?

The "why" is almost irrelevant: The POSIX standard makes it very clear that export is only required to support arguments which are valid names, and anything with a dash is not a valid name. Thus, no POSIX shell is required to support exporting or expanding variable names with dashes, via indirect expansion or otherwise.

It's worth noting that ShellShock -- a major security bug caused by sloppy handling of environment contents -- is fixed in the bash 4.1 present in the current CentOS 6 updates repo; increased rigor in an area which spawned security bugs should be no surprise.

The remainder of this answer will focus on demonstrating that the new behavior of bash 4.1 is explicitly allowed, or even required, by POSIX -- and thus that the prior behavior was an undefined implementation artifact.


To quote POSIX on environment variables:

These strings have the form name=value; names shall not contain the character '='. For values to be portable across systems conforming to IEEE Std 1003.1-2001, the value shall be composed of characters from the portable character set (except NUL and as indicated below). There is no meaning associated with the order of strings in the environment. If more than one string in a process' environment has the same name, the consequences are undefined.

Environment variable names used by the utilities in the Shell and Utilities volume of IEEE Std 1003.1-2001 consist solely of uppercase letters, digits, and the '_' (underscore) from the characters defined in Portable Character Set and do not begin with a digit. Other characters may be permitted by an implementation; applications shall tolerate the presence of such names. Uppercase and lowercase letters shall retain their unique identities and shall not be folded together. The name space of environment variable names containing lowercase letters is reserved for applications. Applications can define any environment variables with names from this name space without modifying the behavior of the standard utilities.

Note: Other applications may have difficulty dealing with environment variable names that start with a digit. For this reason, use of such names is not recommended anywhere.

Thus:

  • Tools (including the shell) are required to fully support environment variable names with uppercase and lowercase letters, digits (except in the first position), and the underscore.
  • Tools (including the shell) may modify their behavior based on environment variables with names that comply with the above and additionally do not contain lowercase letters.
  • Tools (including the shell) should tolerate other names -- meaning they shouldn't crash or misbehave in their presence -- but are not required to support them.

Finally, shells are explicitly allowed to discard environment variable names which are not also shell variable names. From the relevant standard:

It is unspecified whether environment variables that were passed to the shell when it was invoked, but were not used to initialize shell variables (see Shell Variables) because they had invalid names, are included in the environment passed to execl() and (if execl() fails as described above) to the new shell.


Moreover, what defines a valid shell name is well-defined:

Name - In the shell command language, a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit.

Notably, only underscores (not dashes) are considered part of a valid name in a POSIX-compliant shell.


...and the POSIX specification for export explicitly uses the word "name" (which it defined in the text quoted above), and describes it as applying to "variables" (shell variables, the restrictions on names for which are also subject to restrictions quoted elsewhere in this document):

The shell shall give the export attribute to the variables corresponding to the specified names, which shall cause them to be in the environment of subsequently executed commands. If the name of a variable is followed by = word, then the value of that variable shall be set to word.


All the above being said -- if your operating system provides a /proc/self/environ which represents the state of your enviroment variables at process startup (before a shell has, as it's allowed to do, potentially discarded any variables which don't have valid names in shell), you can extract content with invalid names like so:

# using a lower-case name where possible is in line with POSIX guidelines, see above
aws_access_key_id_var="AWS_${BUCKET_NAME}_ACCESS_KEY_ID"
while IFS= read -r -d '' var; do
[[ $var = "$aws_access_key_id_var"=* ]] || continue
val=${var#"${aws_access_key_id_var}="}
break
done </proc/self/environ
echo "Extracted value: $val"

how to declare variable name with - char (dash ) in linux bash script

Rename the variable name as follows:

SM_Read_only="Yes"
SM_write_only="No"

Please, don't use - minus sign in variable names in bash, please refer to the answer, on how to set the proper variable name in bash.

However if you generate the code, based on others output, you can simply process their output with sed:

RESP=$(getValue SM_ Read-rule,Write-rule 2>${ERR_DEV}|sed "s/-/_/g")
RC=$?
eval "$RESP"

How to include dashes (or other special characters) in string concatenation?

Your code works as expected for me.

You don't even need to put the dash outside the quotes, this works also:

datap1="$var1$var2-$var1"

The case where you need to do something special is if the separator character is allowed as part of a variable name, e.g. underscore. If you write

datap1="$var1$var2_$var1"

it will try to find a variable named var2_, and it will fail, so nothing will be substituted; the value will be var1var1. You can put braces around the variable name to delimit it:

datap1="$var1${var2}_$var1"

How to repeat a dash (hyphen) in shell

This throws an error:

$ printf '-%.0s' {1..100}; echo ""
bash: printf: -%: invalid option
printf: usage: printf [-v var] format [arguments]

This works fine under bash:

$ printf -- '-%.0s' {1..100}; echo ""
----------------------------------------------------------------------------------------------------

For other shells, try:

printf -- '-%.0s' $(seq 100); echo ""

The problem was the printf expects that - starts an option. As is common among Unix/POSIX utilities in this type of situation, -- signals to printf to expect no more options.

What is a hyphen beside a shell variable

It's all explained in the Shell Parameter Expansion section of the manual:

${parameter:-word}

If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.

Just before this there is:

Omitting the colon results in a test only for a parameter that is unset.

So:

${X-stuff}

expands to:

  • The expansion of $X if X is set
  • stuff if X is unset.

Try it:

$ unset X
$ echo "${X-stuff}"
stuff
$ X=
$ echo "${X-stuff}"

$ X=hello
$ echo "${X-stuff}"
hello
$

Now your expansion is

${X-}

so you guess that it expands to the expansion of $X if X is set, and to the null string if X is unset.


Why would you want to do this? to me it seems that this is a workaround the set -u:

$ set -u
$ unset X
$ echo "$X"
bash: X: unbound variable
$ echo "${X-}"

$

Finally, your test

if [ -z "${X-}" ]

(note the quotes, they are mandatory) tests whether X is nil (regardless of X being set or not, even if set -u is used).

Name variable from string in Dash

The only way to do this in dash is to use eval, but that is risky unless you know that your string is a valid identifier.

expr "$var" : '[_[:alpha:]][_[:alnum:]]\{0,\}$' && eval "$var=$value"

The call to expr fails (or at least, is intended to fail) if the value of var is anything other than a single valid identifier.



Related Topics



Leave a reply



Submit