15

I was wondering what would be the best way to check if a string as

$str 

contains any of the following characters

!@#$%^&*()_+

I thought of using ASCII values but was a little confused on exactly how that would be implemented.

Or if there is a simpler way to just check the string against the values.

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
deadcell4
  • 6,085
  • 3
  • 14
  • 10
  • 1
    If you just want to check for non-alphanumerics, by the way, that would be `[[ $str = *[^[:alnum:]]* ]]`. – Charles Duffy Oct 29 '14 at 03:13
  • 1
    ...or, to check for any/all kinds of punctuation, `[[ $str = *[[:punct:]]* ]]`. In general, using POSIX character classes (any character class in `man 7 regexp` on Linux will work, even though glob-style patterns aren't POSIX REs) rather than listing out characters one-by-one is a good idea, if there's a character class that fits (or whose negation fits) what you're doing. – Charles Duffy Oct 29 '14 at 03:15

5 Answers5

37

Match it against a glob. You just have to escape the characters that the shell otherwise considers special:

#!/bin/bash
str='some text with @ in it'
if [[ $str == *['!'@#\$%^\&*()_+]* ]]
then
  echo "It contains one of those"
fi
that other guy
  • 116,971
  • 11
  • 170
  • 194
10

This is portable to Dash et al. and IMHO more elegant.

case $str in
  *['!&()'@#$%^*_+]* ) echo yup ;;
esac
tripleee
  • 175,061
  • 34
  • 275
  • 318
  • I'm getting this error: ````` syntax error near unexpected token `&' ` *['!'@#$%^&*()_+]* ) echo yup ;;' ````` – t7e May 26 '22 at 09:30
  • 1
    @t7e Thanks for the feedback; looks like `()&` need to be single-quoted too. Updated the answer. I had tested this in various shells but I was able to repro your problem with `/bin/dash` on MacOS Monterey. – tripleee May 26 '22 at 09:42
  • thanks, now it works. Could you let me know how to exclude square and curly brackets in this script as well `[]` `{}`? – t7e May 28 '22 at 09:48
  • `*['!&(){}[]'@#$%^*_+]* ) echo yup ;;` seems that this works. But vim colors it as if it is a wrong square bracket escaping. Works in zsh, dash and bash on Ubuntu though. Not sure about its portability. – t7e May 28 '22 at 10:03
  • You might want to backslash-escape instead of single-quote some characters instead in the hopes that it will appease `vim`. Obviously add any additional characters you like inside the square brackets. – tripleee May 28 '22 at 13:57
7

You can also use a regexp:

if [[ $str =~ ['!@#$%^&*()_+'] ]]; then
    echo yes
else
    echo no
fi

Some notes:

  • The regexp includes the square brackets
  • The regexp must not be quoted (so $str =~ '[!...+]' would not work).
  • There is no need to escape chars as is necessary with the glob approach in another answer, because the chars are between the brackets, where they are taken literally by regexp
  • as with glob pattern [] means "anything in the contained string"
  • because the pattern does not start with ^ or end with $ there will be a match anywhere in the $str.
Oliver
  • 27,510
  • 9
  • 72
  • 103
  • It could not catch a `[` or `]`, I tried including them in the list as: `'!@#$%^&*()_+[]'` didn't work, `'!@#$%^&*()_+\[\]'` didn't work either. How can `[,]` be included? – quanta Jun 30 '20 at 02:51
  • Just checked, if we put only one of them at a time in that list, it works. Putting them together (meaning in one go, not necessarily together in space only) doesn't work. – quanta Jun 30 '20 at 02:54
  • @quanta try `if [[ $str =~ ['!@#$%^&*()\[\]_+'] ]]; then` – Oliver Jun 30 '20 at 12:43
  • `str="some string ]"; [[ $str =~ ['!@#$%^&*()\[\]_+'] ]] && echo "Yes"` returns nothing. Ofcourse using an `or` will work: `$str =~ ['[!@#$%^&*()_+'] || $str =~ [']!@#$%^&*()_+']` but this is not a beautiful solution! What is so special about `[` and `]` together?? Even if they are separated! – quanta Jul 01 '20 at 13:40
  • The right bracket is the problem, the left one is not special and can be anywhere the in the bracket expression, whereas the right one is recognized only if it is first: `[[ $str =~ [']!@#$%^&*[()_+'] ]]`. See https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap09.html#tag_09_03_05: "The right-bracket ( ']' ) shall lose its special meaning and represent itself in a bracket expression if it occurs first in the list" – Oliver Jul 01 '20 at 18:32
  • @Oliver , how can we add check for single and double quotes ( ' and ") along with this set? – Darshil Shah Aug 30 '21 at 07:39
1

Using expr

str='some text with @ in it'
if [ `expr "$str" : ".*[!@#\$%^\&*()_+].*"` -gt 0 ];
    then 
       echo "This str contain sspecial symbol"; 
       fi
Hackaholic
  • 19,069
  • 5
  • 54
  • 72
  • There was a time when `expr` was unavoidable but this wasn't one of those cases even back then in the dark ages. – tripleee Oct 06 '18 at 09:22
0

I think one simple way of doing would be like remove any alphanumeric characters and space.

echo "$str" | grep -v "^[a-zA-Z0-9 ]*$"

If you have a bunch of strings then put them in a file like strFile and following command would do the needful.

cat strFile | grep -v "^[a-zA-Z0-9 ]*$"

R. Kumar
  • 103
  • 5