0

Consider this...

#!/bin/bash
declare STR='test'
declare SUB=''
[[ "${STR}" == *"${SUB}"* ]] && echo 'match'

This appears to resolve or evaluate to true? This makes no sense to me.

To get the expected result you have to test if the SUB string is empty?

#!/bin/bash
declare STR='test'
declare SUB=''
[[ ! -z "${SUB}" ]] && [[ "${STR}" == *"${SUB}"* ]] && echo 'match'

Is this some quirk with BASH or such? If the sub string is NOT in the string should it not return false?

5
  • 4
    Why's it odd? The empty substring, by nature, exists everywhere: it's before, after, and between each character of any string you like. Why would [[ foo = * ]] be different from [[ foo = *'' ]] or [[ foo = *''* ]] or [[ foo = ''* ]]? Commented Apr 27, 2021 at 15:56
  • I've never known any language to exist that doesn't behave this way. Compare to Python: '' in 'foo' is true. So is 'foo'.endswith(''), and 'foo'.startswith(''). Commented Apr 27, 2021 at 15:58
  • The empty string doesn't exist as a distinct thing to match. *"${SUB}"* is exactly identical to **, which is semantically the same as * (although with multiple different ways to match). Commented Apr 27, 2021 at 15:58
  • *"${SUB}"* Why did you put asterisks? [[ 'whatever' == * ]] will always match! Not an odd behavior at all... when SUB='' is left blank it will match, when SUB='foo' has "some other" value it will NOT match. Commented Apr 27, 2021 at 15:59
  • @dachshund-digital, ...for example, see ideone.com/X9jyaj showing the same behavior (detecting a match at the very first character) for C's strstr() function. Commented Apr 27, 2021 at 16:07

2 Answers 2

1

The empty string is part of every string. Thus, testing whether an empty string is a substring of anything else is always true.


This is not specific to bash or in any way unusual; you can check it in other languages.

  • Python: print('' in 'foo') prints True.
  • Java: String("foo").contains("") returns true.
  • C: strstr("foo", "") returns a pointer to the first character in foo, meaning it found a match.
  • Ruby: "foo".include? "" returns true.
Sign up to request clarification or add additional context in comments.

Comments

0

Yes, you should explicitly check for a possible empty string, but I'd use -n instead of a not, and in bash you can make it a single compound condition check.

$: x=abcdefg
$: y=cde
$: [[ -n "$y" && "$x" =~ $y ]] && echo match || echo no
match
$: y=
$: [[ -n "$y" && "$x" =~ $y ]] && echo match || echo no
no

...and you don't need the leading and trailing globs, they don't really add anything.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.