Test whether a string contains a literal asterisk
chepner's helpful answer explains the problem with your original approach well.
The following prompts until a literal *
is found anywhere in the user input:
until [[ $string == *'*'* ]]; do echo "just give me a string with an asterisk, for crying out loud" read -r stringdone
[[ ... ]]
rather than[ ... ]
must be used in order to enable pattern matching on the RHS of==
(=
).- Unless you're writing POSIX-compliant scripts (for
/bin/sh
), where only[ ... ]
is supported, consider using[[ ... ]]
routinely, because it offers more features and fewer surprises: see this answer of mine.
- Unless you're writing POSIX-compliant scripts (for
*'*'*
is a pattern that says: match a literal*
- the single-quoted part - anywhere in the string; the unquoted*
instances represent any run of characters.- These patterns are the same as the ones used in filename globbing and are not regular expressions.
- However, Bash also offers regular expression matching, via
[[ ... =~ ... ]]
. Thus, the conditional could also be written as[[ $string =~ '*' ]]
or[[ $string =~ \* ]]
-r
should be used withread
as a matter of habit, to prevent unexpected processing of\
chars.
@mklement's answer actually provides a solution; I am primarily describing the problem.
You aren't comparing the value of the parameter string
; you are comparing the literal string string
. This has nothing to do with globs (you are otherwise quoting things properly.
until [ "$string" = "[asteriskstuff]" ]; do read stringdone
You don't need to quote the argument to read
, since it is a literal string that needs to be a valid identifier, which can only consist of _
, letters, and numbers. Quoting it doesn't hurt, though.