Check if a string contains asterisk (*) [duplicate]
Asked Answered
C

8

11

I want to check if my string contains one or more asterisks.

I have tried this:

if [[ $date_alarm =~ .*\*.* ]]
then
    ...
fi

It worked when I launch the script directly, but not if this script is called during shutdown (script installed in run level 0 and 6 via update-rc.d)

Any idea, suggestion?

Cachet answered 28/7, 2009 at 12:4 Comment(2)
My guess is your init system doesn't use /bin/bash as an interpreter, instead it will use /bin/sh.Punchball
If William's answer worked, don't forget to click the "Accept answer" button!Meghan
C
8

Always quote strings.

To check if the string $date_alarm contains an asterisk, you can do:

if echo "$date_alarm" | grep '*' > /dev/null; then
    ...
fi

but it's more idiomatic to use a case statement:

case "$date_alarm" in *\**) ...;; esac

Note the quotes. Even thought the quotes really aren't necessary in the case statement (field splitting won't happen there), it is considered best practice to include them.

Capacious answered 28/7, 2009 at 12:9 Comment(4)
Using grep is overkill, and using echo to send string to grep is even more overkill. grep -q '*' <<< "x$date_alarm" would be plenty here.Determine
Using an external process for something the shell supports natively is ugly and inefficient. My vote goes to the case solution which is fast, portable, and idiomatic.Grandpa
@triplee 15 years ago I actually gave this answer? I wish I had given some more explanation, as this looks truly bizarre. Interesting that 2 comments came in the last day.Capacious
The recent answer provoked some attention.Grandpa
C
3
case "$date_alarm" in
*\**)
  ...
  break
  ;;
*)
  # else part
  ...
  ;;
esac

The syntax is, well, /bin/sh, but it works.

Collyrium answered 28/7, 2009 at 12:24 Comment(0)
F
1

what happens if you replace

if [[ $date_alarm =~ .*\*.* ]]

with

if [[ "$date_alarm" =~ .*\*.* ]]

you might also want to try:

if [[ "$date_alarm" =~ '\*+' ]]

not sure about that one...

regards

Feuillant answered 28/7, 2009 at 12:12 Comment(2)
if [[ "$date_alarm" =~ .**.* ]] Don't work, but as I said the strange thing is that it doesn't work only in init context during shutdown if [[ "$date_alarm" =~ '*+' ]] not tested TahnksCachet
Quote the pattern: if [[ "$date_alarm" =~ ".**.*" ]]Totalizer
T
0
if echo $date_alarm|perl -e '$_=<>;exit(!/\*/)'
then
    ...
fi
Toll answered 28/7, 2009 at 12:17 Comment(0)
C
0

Finally

if echo x"$date_alarm" | grep '*' > /dev/null; then

did the trick

Strange thing =~ .*. doesn't work only in init context during shutdown, but work perfectly if launch in bash context....

Cachet answered 28/7, 2009 at 12:39 Comment(1)
no need to call external program such as grep to do what you want. In bash, the case statement should suffice.Varden
P
0
expr "$date_alarm" : ".*\*.*"
Percussion answered 28/10, 2010 at 14:37 Comment(1)
a bit of explanation would be nice ;)Blintz
F
0

No need to redirect stdout like others do. Use the -q option of grep instead:

if echo x"$date_alarm" | grep -q '*' ; then

Flighty answered 10/11, 2017 at 20:50 Comment(0)
D
0

Dang... 15 years and nobody suggested the simplest solution:

if [[ "$date_alarm" == *"*"* ]]; then

If you want a more portable solution that works on shells other than bash, see the answer regarding case statement to match on *\**.

Also, to anybody doing this:
echo "$stuff" | some_prog
instead, do this:
some_prog <<< "$stuff"

No need to invoke echo to send a string as input, you just need to <<< it in at the end, rather than pipe it into the beginning. (output > redirects come after input <<<).

I recommend using an IDE with shellcheck enabled, it will teach you many, many things about bash.

Determine answered 1/8 at 6:31 Comment(3)
This still won't work if the shell isn't Bash.Grandpa
Also, the double quotes are conceptually quite simllar to the suggestion to backslash-escape the literal asterisk, provided in an earlier answer from 2009.Grandpa
Well, the original question was specifically tagged with bash, so I took the liberty to show how it can be done in a simple, bash-compatible form that is much easier to stuff into places like if statements. I'll add a note that the case solution is more portable though. Also, I used == not =~, which performs regular glob style matches instead of regex. I tend to use the [[ " $var_name " == *" thing-to-match "* ]] pattern to search for tokens a lot, which I find easier to read when using == instead of =~.Determine

© 2022 - 2024 — McMap. All rights reserved.