6

Basically looking for a string that contains an asterisk, looked all around for one that relates to an until loop but to no avail!

e.g. the user would basically keep typing in strings and the program will reject them until one that has an asterisk pops up.

then at this point it will echo a message [cant go into details sorry]

code:

until [ "string" == "[asteriskstuff]" ]
do

  echo "just give me a string with an asterisk for crying out loud"

  read "string"

done

when the user stops inputting hi and then decides to input hi* it will then show the echo message basically I just want to bypass the bleedin' asterisk because [asteriskstuff] is the area where I always falter!

all help appreciated!

SUMMARY: How can I bypass an asterisk in a simple way for an until loop?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • We need to know where asteriskstuff comes from. Is it a variable? Does it have a literal part? – Jeremy Gurr Dec 12 '16 at 15:11
  • 1
    `[ ]` is an alternate name for [the POSIX-specified `test` command](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html). The only string comparison operator it's guaranteed by the standard to support is `=`, not `==` (and there's no standard-defined substring match operation at all). Bash supports `==` as an extension, but if you want extensions, you should be using `[[ ]]` instead, which is the *explicitly* extended form of the operator that also supports globbing, regular expressions, and lots of other goodness. – Charles Duffy Dec 12 '16 at 17:03
  • 1
    BTW, it's not in any way whatsoever clear what you mean by most of this message. What do you mean by the word "bypass" in "bypass an asterisk"? Do you want to get the same comparison you'd have **without** the asterisk there? Do you want to exit the loop in that condition? Something else? – Charles Duffy Dec 12 '16 at 17:06

2 Answers2

10

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 string
done
  • [[ ... ]] 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.
  • *'*'* 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 with read as a matter of habit, to prevent unexpected processing of \ chars.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    Thanks for explaining the fact that double brackets must be used, I've constantly been using single brackets since they are simpler to do and seem to get the job done. That was one of the main issues. – Student of Art Dec 14 '16 at 05:20
  • 1
    @StudentofArt My pleasure; in Bash scripts, if you don't need to be POSIX-compliant, using `[[ ... ]]` is usually worth it - I've updated my answer with a link contrasting `[[ ... ]]` and `[ ... ]`. – mklement0 Dec 14 '16 at 14:01
3

@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 string
done

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.

Community
  • 1
  • 1
chepner
  • 497,756
  • 71
  • 530
  • 681