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?

Kusalananda
  • 333,661
bigstreet
  • 3
  • 2

2 Answers2

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

Kusalananda
  • 333,661
  • What is read -s -r mean? – bigstreet Aug 09 '22 at 07: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). – Kusalananda Aug 09 '22 at 07: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 ]]
ilkkachu
  • 138,973