How to check in bash that string contains only blank characters as space, tab, new line? I'm trying this but it doesn't work:
if [[ "$1" == #([\t\n ]) ]]; then
echo "Empty"
fi
Using a regular expression:
if [[ $1 =~ ^[[:space:]]+$ ]]; then
echo "Only whitespace"
else
echo "There are non-whitespace characters."
fi
Use * instead of + if you also want to match empty strings.
Convert it to an array, it will be empty if string contains only blank characters
string=" "
array=($string)
[[ ${!array[#]} ]] && echo fail || echo ok
Related
I have a variable $FOO with values one two three.
echo $FOO
one two three
Is there a way in bash to check if two exists and exactly matches one of the values of $FOO
I can do this
if [[ "two" =~ ^(one|two|three)$ ]]; then
echo "two is in the list"
else
echo "two is not in the list"
fi
And it works, but I'd like to check using the actual variable $FOO and not (one|two|three)$
Is this possible?
If the items in $FOO are guaranteed to be separated by spaces, you can use this:
if [[ " $FOO " = *" $TWO "* ]]; then
...
Note that this reverses the roles of $FOO and $TWO from what you might expect; it treats $FOO as the string to check against a pattern, and the pattern is essentially "something that contains $TWO". It also adds explicit spaces to $TWO to make sure it matches only full items, and similarly adds spaces around $FOO so that'll match the first and last items in it.
If the delimiters in $FOO might be tabs or other space-like characters, you can use this more complex pattern:
if [[ " $FOO " = *[[:space:]]"$TWO"[[:space:]]* ]]; then
Heres how to do it below
FOO='one two three'
TWO='two'
if [[ "$FOO" == *"$TWO"* ]]; then
echo "two is in the list"
fi
wildcard aka * is a symbol used to represent zero, one or more characters.
Using an array
$ FOO=(one two three)
$ n=0;while [[ $n -lt ${#FOO} ]]; do [[ "${FOO[$n]}" == "two" ]] && echo "two is in the list"; n=$(( $n + 1 )); done
two is in the list
You can construct pattern with :
foo=(one two three)
pattern="^($(IFS="|"; echo "${foo[*]}"))\$"
if [[ two =~ $pattern ]]; then
echo "two is in the list"
else
echo "two is not in the list"
fi
It's odd that nobody posted case. It's the simplest and most portable. Notice the added spaces around $FOO.
case " $FOO " in
*" two "*) echo two is in the list; ;;
*) echo two is not in the list; ;;
esac
You can try something like this
FOO="one two three"
foo=( $FOO )
if [[ "${foo[*]}" =~ ' two ' ]]
then
echo "two is in the list"
else
echo "two is not in the list"
fi
which will work for the simple cases (i.e. no spaces in the values)
This should also work for you.
FOO='one two three'
TWO='two'
if [[ "$FOO" =~ "$TWO"( |$) ]]
then
echo "two is in the list"
else
echo "two is not in the list"
fi
This will give an exact pattern match.
I tried the following but without success
[root#OBAMA~]# bash
[root#OBAMA~]# a=HelloWorld
[root#OBAMA~]# [[ $a == [A-Za-z] ]] && echo "YES ITS STRING"
( the command not prints anything )
[root#OBAMA~]# [[ $a == [A-Z][a-z] ]] && echo "YES ITS STRING"
( the command not prints anything )
Change your command lke below.
$ [[ $a =~ [A-Za-z]+ ]] && echo "YES ITS STRING"
YES ITS STRING
Use =~ operator to test an input string against a regex.
Add + next to the character class, so that it would repeat the previous pattern or token one or more times. Here it's unnecessary.
Add anchors , in-order to do an exact string match. [[ $a =~ [A-Za-z] ]] && echo "YES ITS STRING" alone will print the string YES ITS STRING because the variable a contains atleast an alphabet.
$ a="HelloWorld"
$ [[ $a =~ ^[A-Za-z]+$ ]] && echo "YES ITS STRING"
YES ITS STRING
$ a="Hello World"
$ [[ $a =~ ^[A-Za-z]+$ ]] && echo "YES ITS STRING"
$
how do you define "a string"
[[ -n $a ]] && echo variable a is not empty
[[ $a == *[[:alpha:]]* ]] && echo variable a contains a letter
shopt -s extglob failglob
[[ $a == +([[:alpha:]]) ]] && echo variable a only has letters
Your glob expressions are not matching because your checking that your variable contains only 1 character or 2 characters.
String:
name#gmail.com
Checking for:
#
.com
My code
if [[ $word =~ "#" ]]
then
if [[ $word =~ ".com" || $word =~ ".ca" ]]
My problem
name#.com
The above example gets passed, which is not what I want. How do I check for characters (1 or more) between "#" and ".com"?
You can use a very very basic regex:
[[ $var =~ ^[a-z]+#[a-z]+\.[a-z]+$ ]]
It looks for a string being exactly like this:
at least one a-z char
#
at least one a-z char
.
at least one a-z char
It can get as complicated as you want, see for example Email check regular expression with bash script.
See in action
$ var="a#b.com"
$ [[ $var =~ ^[a-z]+#[a-z]+\.[a-z]+$ ]] && echo "kind of valid email"
kind of valid email
$ var="a#.com"
$ [[ $var =~ ^[a-z]+#[a-z]+\.[a-z]+$ ]] && echo "kind of valid email"
$
why not go for other tools like perl:
> echo "x#gmail.com" | perl -lne 'print $1 if(/#(.*?)\.com/)'
gmail
The glob pattern would be: [[ $word == ?*#?*.#(com|ca) ]]
? matches any single character and * matches zero or more characters
#(p1|p2|p3|...) is an extended globbing pattern that matches one of the given patterns. This requires:
shopt -s extglob
testing:
$ for word in #.com #a.ca a#.com a#b.ca a#b.org; do
echo -ne "$word\t"
[[ $word == ?*#?*.#(com|ca) ]] && echo matches || echo does not match
done
#.com does not match
#a.ca does not match
a#.com does not match
a#b.ca matches
a#b.org does not match
When given a string I want to search for a substring which matches two characters (9&0. 0 should be the last character in that substring) and exactly two characters in between them
string="asd20 92x0x 72x0 YX92s0 0xx0 92x0x"
#I want to select substring YX92s0 from that above string
for var in $string
do
if [[ "$var" == *9**0 ]]; then
echo $var // Should print YX92s0 only
fi
done
Obviously this above command doesn't work.
You match each element against the pattern *9??0. There are several ways you can do this; here's one that uses the string to set the positional parameters in a subshell, then iterates over them in a for loop:
( set -- $string
for elt; do [[ $elt == *9??0 ]] && { echo "found"; exit; }; done )
string="asd20 92x0x 72x0 X92s0 0xx0"
if [[ $string =~ [[:space:]].?9.{2}0[[:space:]] ]]; then
echo "found"
fi
Or better, taking advantage of word spliting :
string="asd20 92x0x 72x0 X92s0 0xx0"
for s in $string; do
if [[ $s =~ (.*9.{2}0) ]]; then
echo "${BASH_REMATCH[1]} found"
fi
done
This is regex with bash.
Say a string might be like "a b '' c '' d". How can I check that there is single/double quote and space contained in the string?
You can use regular expressions in bash:
string="a b '' c '' d"
if [[ "$string" =~ \ |\' ]] # slightly more readable: if [[ "$string" =~ ( |\') ]]
then
echo "Matches"
else
echo "No matches"
fi
Edit:
For reasons obvious above, it's better to put the regex in a variable:
pattern=" |'"
if [[ $string =~ $pattern ]]
And quotes aren't necessary inside double square brackets. They can't be used on the right or the regex is changed to a literal string.
case "$var" in
*\ * )
echo "match"
;;
*)
echo "no match"
;;
esac
You could do this, without the need for any backslashes or external commands:
# string matching
if [[ $string = *" "* ]]; then
echo "string contains one or more spaces"
else
echo "string doesn't contain spaces"
fi
# regex matching
re="[[:space:]]+"
if [[ $string =~ $re ]]; then
echo "string contains one or more spaces"
else
echo "string doesn't contain spaces"
fi
Based on this benchmark, the string match is much faster than the regex one.
Related:
How to check if a string contains a substring in Bash
[[ "$str" = "${str%[[:space:]]*}" ]] && echo "no spaces" || echo "has spaces"
string="a b '' c '' d"
if [ "$string" == "${string//[\' ]/}" ]
then
echo did not contain space or single quote
else
echo did contain space or single quote
fi
The portable way to do this is with grep:
S="a b '' c '' d"
if echo $S | grep -E '[ "]' >/dev/null
then
echo "It's a match"
fi
...a bit ugly, but guaranteed to work everywhere.
How about an approach similar to:
$ A="some string"; echo $A | grep \ | wc -l
1
$ A="somestring"; echo $A | grep \ | wc -l
0
?
function foo() {
echo "String: $*"
SPACES=$(($#-1))
echo "Spaces: $SPACES"
QUOTES=0
for i in $*; do
if [ "$i" == "'" ]; then
QUOTES=$((QUOTES+1))
fi
done
echo "Quotes: $QUOTES"
echo
}
S="string with spaces"
foo $S
S="single' 'quotes"
foo $S
S="single '' quotes"
foo $S
S="single ' ' quotes"
foo $S
yields:
String: string with spaces
Spaces: 2
Quotes: 0
String: single' 'quotes
Spaces: 1
Quotes: 0
String: single '' quotes
Spaces: 2
Quotes: 0
String: single ' ' quotes
Spaces: 3
Quotes: 2
What about this:
[[ $var == ${var//[ \"]/_} ]] && echo "quotes or spaces not found"
or if you like this:
if [[ $var == ${var//[ \"]/_} ]] ; then
echo "quotes or spaces not found"
else
echo "found quotes or spaces"
fi
Explanation:
I'm evaluating a comparison between the variable ${var} and the variable ${var} itself after a on-the-fly non-destructive string substitution of all the quotes and spaces with an underscore.
Examples:
${var// /_} # Substitute all spaces with underscores
The following code substitute all characters between the squared brackets (space and quotes) with an underscore. Note that quotes has to be protected with backslash:
${var//[ \"]/_}
I do wonder why nobody mentioned the [:space:] set. Usually your not only interested in detecting the space character. I often need to detect any white space, e.g. TAB. The "grep" example would look like this:
$ echo " " | egrep -q "[:space:]" && echo "Has no Whitespace" || echo "Has Whitespace"
Has Whitespace
$ echo "a" | egrep -q "[:space:]" && echo "Has no Whitespace" || echo "Has Whitespace"
Has no Whitespace