1

I've been working on a sample bash program to practice bash scripting, but whenever I try to run it with the correct variables, it outputs "[: =: unary operator expected" and quits.

#! /bin/bash
clear
i=""
P="PASSWORD"
echo "Please enter your password"
while [ $i = "PASSWORD" ]
do
  read $i
done
Petter Hesselberg
  • 5,062
  • 2
  • 24
  • 42
Joe Dimagio
  • 55
  • 1
  • 1
  • 6

2 Answers2

8

if $i is empty, you got syntax error because of not enough arguments [ = "PASSWORD" ]

  1. you can use bash option [[ $i = "PASSWORD" ]] But it is bash operator, and it could be not compatible with old shells

  2. you can put your variable in quotas, like [ "$i" = "PASSWORD" ] This is preferred thing, you also will fix an issue, if your variable contains spaces or shell expansion marks like *, ?, [1..9]

Saboteur
  • 1,331
  • 5
  • 12
  • 2
    Personally, I prefer to *always* double-quote variable references (even in places like most uses in `[[ ]]` where it's safe to leave them off), unless there's a specific reason *not* to double-quote them. This saves me trying to remember all the cases where it is vs. isn't safe. For example, did you know that in a `[[ "$a" = "$b" ]]` test, it's safe to leave the double-quotes off of the left side (`$a`), but leaving them off the right side (`$b`) changes the meaning of the test? (Without quotes, it'll treat `$b` as a glob pattern rather than a plain string.) – Gordon Davisson Apr 14 '20 at 23:45
  • In [How to Answer](https://stackoverflow.com/help/how-to-answer), note the section _Answer Well-Asked Questions_, and therein the note regarding questions that "have been asked and answered many times before". – Charles Duffy Nov 29 '22 at 16:08
1

but whenever I try to run it with the correct variables, it outputs "[: =: unary operator expected" and quits.

That's because you have an unquoted/empty variable inside the [ , either quote your variables or use [[ which is safer and more robust.

while [ $i = "PASSWORD" ]

The value of $i is empty there is no way a user can give the value/input, so it will fail


Edit: As mentioned by @William Pursell, Regardless which test you are using, it still has some pitfall, the lesson here is to sanitize/validate the input, e.g. test it if it is indeed a digit, if it is not empty and so on.


Try this, It might do what you wanted.

#!/usr/bin/env bash

clear
p="PASSWORD"
read -rp "Please enter your password: " input  ##: Ask the user to enter the password

until [[ $p == "$input" ]]; do ##: The loop will continue until both vars matches
  clear
  printf 'Please try again! %s does not match..\n' >&2 "$input"
  read -rp "Please enter your password: " input
done

##: If it matches print a message and the value of input
printf '%s is a match!\n' "$input" 
Jetchisel
  • 7,493
  • 2
  • 19
  • 18
  • 1
    Consider `i=foo; [[ i -gt 0 ]]` A robust operator would repot an error that you are trying to use an integer comparison operator with a non-integer string. `[[` has different pitfalls than `test`, and you should not use either without understanding those pitfalls. – William Pursell Apr 14 '20 at 21:05
  • Right, thank you for that wonderful comment. I will update my answer. – Jetchisel Apr 14 '20 at 21:06
  • 1
    `[[ $input == $p ]]` is not safe, because if `$p` contains any glob (wildcard) characters it'll be treated as a pattern instead of just being compared as a literal string. – Gordon Davisson Apr 14 '20 at 23:48