Actually, I am doing some assignment by follow:

1: Write a program called valid that prints "yes" if its argument is a valid shell variable name and "no" otherwise:

What I am doing is I want to find some value which includes some regular expression, such as [0-9]* by using 'grep' command. But I have no idea how to grab some value including that expression from the argument I input, since 'grep' command is basically to capture some line in the file. Any help will be really appreciated

  • 1
    Do you think they’re expecting a bash script from you? And that the valid variable name is for the bash shell? How much have you learned this far, besides grep? Anything about referring to script parap?
    – Jeff Schaller
    May 30, 2018 at 20:17
  • Yes, I need to code for a bash script. When script name is 'valid', and I run it as follow: valid 1234 -> it has to print yes or no depending on argument is correct name of variable May 30, 2018 at 20:23
  • It seems like the piece you're missing is how to get the argument. In bash, they are known as the "positional parameters", $1, $2, etc May 30, 2018 at 20:32
  • 4 answers and still no grep!
    – Jeff Schaller
    May 30, 2018 at 21:57

4 Answers 4


This doesn't use grep, but as a point of reference, you could use bash's =~ conditional operator to compare the script's first argument with the regular expression class for a name, which is defined by the Bash Reference Manual as:

A word consisting solely of letters, numbers, and underscores, and beginning with a letter or underscore. Names are used as shell variable and function names.

$ cat isvarname
if [ "$#" -ne 1 ]
   echo "Usage: $0 a-string"
   exit 1

if [[ "$1" =~ ^[[:alpha:]_][[:alnum:]_]*$ ]]
  echo yes
  echo no
  • Thank you very much and it was very helpful. By the way, how would you know that regular expression? such as =~ ^[[:alpha:]_][[:alnum:]_]*$ ]] May 30, 2018 at 20:33
  • Please don't rush to accept this answer, particularly since I avoided using grep! =~ accepts regular expressions, so I just did it in-shell. To learn more, start with conditional expressions and man -s7 regex for a list of character classes. See the regular-expression tag on this site for more, such as unix.stackexchange.com/questions/119905/…
    – Jeff Schaller
    May 30, 2018 at 20:37
  • 1
    Can use extended pattern instead of regex: [[ $1 == [[:alpha:]_]*([[:alnum:]_]) ]] May 30, 2018 at 20:40

In bash a valid variable name is made of one or more single-byte characters with the first one being alphabetical or underscore, and the remaining ones if any being alphabetical, 0123456789 or underscore.

For instance Stéphane is a valid variable name only in locales where é is single-byte like in ISO-8859-1 where it's the 0xE9 byte, not in UTF-8 where it's encoded as 0xC3 0xA9.

You could do something like:

#! /usr/bin/env bash
is_single_byte() {
  local length_in_bytes length_in_chars
  local LC_ALL=C
  ((length_in_bytes == length_in_chars))

for var do
  if is_single_byte "$var" && [[ $var =~ $re ]]; then
    printf '"%s" is a valid variable name\n' "$var"
    printf '"%s" is not a valid variable name\n' "$var"

The first command line argument is available as $1. A valid shell variable name starts with a alphabetic character (or underscore) and continues with alphanumerics (or underscores).

Two shell patterns that matches an invalid shell variable name is




You may use case ... esac to do pattern matching against a variable's value.

Spoiler warning:

case "$1" in
        echo 'NO'
        echo 'YES'
This also answers "NO" for a variable whose name is empty. Note that this is using shell globbing patterns, not regular expressions, and that it runs in any POSIX shell, not just bash.


$ ./script.sh _ae
$ ./script.sh 0a9oe
$ ./script.sh aoeat
$ ./script.sh aoeat-aoe
  • _ is a valid variable name. In most locales, [a-z] matches a lot more than the 26 English letters from a to z. Same for [0-9] and 0123456789 in some shells like bash or ksh93. May 30, 2018 at 20:45
  • @StéphaneChazelas Thanks for the reminders!
    – Kusalananda
    May 30, 2018 at 20:48
if [[ $var =~ [\`\$\=\/] || $var =~ \[ ]]; then
    echo 'no'
declare "$var"=test 2>/dev/null
if [[ ${!var} == 'test' || $1 == 'var' ]]; then
    echo 'yes'
    echo 'no'

This will try to assign the value test to the provided value. If it succeeds (if the value is a valid variable name) it will match the if test and echo yes, else it will echo no.

  • 3
    Generally a bad idea to use eval: bash ./your_script '(echo rm /very/important/files); foo' -- by the time the syntax error occurs, your files are already deleted. May 30, 2018 at 20:31
  • ./script '/usr/sbin/shutdown -h; x' :)
    – Jeff Schaller
    May 30, 2018 at 20:33
  • @StéphaneChazelas: Updated again, however I cannot get it to accept a[1] either way.
    – jesse_b
    May 30, 2018 at 22:25
  • @StéphaneChazelas: Quoted $var to prevent globbing. Also I would argue that it's a good thing to tell students RANDOM, EUID, and UID are not valid variable names. :p
    – jesse_b
    May 30, 2018 at 22:40
  • Modified again.
    – jesse_b
    May 30, 2018 at 22:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .