0

I am just checking whether the password contains a small and capital case letter, I am getting an error at line 19.

myscript.sh:

#!bin/sh

read password
conditionarr=(0 0)

if [[ $password =~ [A-Z] ]]
then
   condtionarr[1]=1
fi


if [[ $password =~ [a-z] ]]
then
   conditionarr[0]=1
fi


if [ ${conditionarr[0]} == 1 || ${conditionarr[1]} == 1 ]
then
    printf "%s" "Yes\n "
else
    printf "%s" "No\n"
fi

The error:

./myscript.sh: line 19: [: missing `]'

./myscript.sh: line 19: 0: command not found

What is wrong with this code? Can anyone tell me how to fix this?

1
  • Yeah , it's a mistake, thankyou Commented Aug 9, 2022 at 8:54

2 Answers 2

2

There are a couple of issues in your code:

  • The #!-line should read #!/bin/bash (or whatever the full absolute path is to the bash interpreter or your system). Note that you are using shell code that requires the use of bash, so pointing the #!-line to the sh interpreter would not be correct as that shell may not understand things like the non-standard [[ ... ]], or the use of arrays.

  • Passwords should probably be read using IFS= read -s -r in bash to avoid echoing the input to the terminal, and to allow the use of \ without issues, and to allow flanking spaces etc.

  • Multiple tests are better written [ ... ] || [ ... ]. This is what causes your actual error message. The [ utility does not know about ||.

Suggestion:

#!/bin/bash

IFS= read -p 'Enter password: ' -sr password
check=(0 0)

[[ $password =~ [A-Z] ]] && check[0]=1
[[ $password =~ [a-z] ]] && check[1]=1

if [ "${check[0]}" = 1 ] || [ "${check[1]}" = 1 ]; then
    echo yes
else
    echo no
fi

Or, getting rid of the need for the array:

#!/bin/bash

IFS= read -p 'Enter password: ' -sr password

if [[ $password =~ [A-Z] ]] ||
   [[ $password =~ [a-z] ]]
then
    echo yes
else
    echo no
fi

Note that testing the $password string for matches of [A-Z] or for matches of [a-z] can be done in one test with [A-Za-z].

In the sh shell, you could write your script like this:

#!/bin/sh

printf 'Enter password: ' >&2

state=$(stty -g)    # save stty state
stty -echo          # turn off local echo
IFS= read -r password
stty "$state"       # reset stty state to original

case $password in
        *[A-Za-z]*)
                echo yes
                ;;
        *)
                echo no
esac

Note that I've combined the tests for upper and lower case characters into a single test, and that the patterns used by case are shell globbing patterns, not regular expressions.

If you need to check for upper and lower case letters, you still need the two separate tests:

case $password in (*[A-Z]*) check1=true;; (*) check1=false; esac
case $password in (*[a-z]*) check2=true;; (*) check2=false; esac

if "$check1" && "$check2"; then
    echo yes
else
    echo no
fi
2
  • What is read -s -r mean? Commented Aug 9, 2022 at 7:52
  • @bigstreet See help read in an interactive bash session, but -s turns off local echo so that the password is not displayed while you type it, and -r turns off special processing of some characters when preceded by \ in the input (this allows \ to be used in passwords). Commented Aug 9, 2022 at 7:53
1

Note how you switched from [[ to [ for that last condition:

if [[ $password =~ [a-z] ]]

if [ ${conditionarr[0]} == 1 || ${conditionarr[1]} == 1 ]

There's a big difference between the two, namely that [[ is a special shell construct, and has its own syntax, while [ is just a regular command.

See:

In [ ${conditionarr[0]} == 1 || ..., the || terminates the command, so what runs is just [ whatever == 1. But [ expects to see a ] as a final argument, so that the command looks nicer. There isn't one now, so it complains. (Also with [, you should quote the variable expansions for all the usual reasons, and use = instead of ==, as the latter isn't standard.)

You could use either of

if [    "${conditionarr[0]}" = 1 ] || [    "${conditionarr[1]}" = 1 ]
# or
if test "${conditionarr[0]}" = 1   || test "${conditionarr[1]}" = 1

but it'd be easier to just switch to [[ instead, since it does support || within it and is actually safer with missing quoting (on the left-hand side of == anyway):

if [[ ${conditionarr[0]} == 1 || ${conditionarr[1]} == 1 ]]

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.