This guide shows you several reliable ways to check whether a bash string contains a substring on Linux. You’ll learn the most common methods—using the [[ ]] operator, case, grep, and others—with clear examples you can copy directly into your scripts.
What You’ll Need
- A Linux system with a bash shell (version 4 or later is recommended).
- Basic familiarity with opening a terminal and running commands.
- No special packages are required—all methods use built-in bash features or standard utilities.
Step-by-Step
- Open a terminal window. You’ll be testing commands interactively, so any terminal emulator works.
- Define your strings. Start by setting two variables: one for the full string and one for the substring you want to find. For example:
full="Hello, Linux world"sub="Linux" - Use the
[[ ]]operator with*wildcards (recommended). This is the simplest and fastest method in bash. Run:if [[ "$full" == *"$sub"* ]]; then echo "Found"; else echo "Not found"; fi
This works because*matches any sequence of characters before and after the substring. The quotes around$subensure that spaces or special characters in the substring are treated literally. - Check with
casefor POSIX compatibility. If you need your script to run insh(dash) as well, use:case "$full" in *"$sub"*) echo "Found";; *) echo "Not found";; esac
This works exactly like the[[ ]]method but is portable to older shells. - Use
grepfor pattern matching or when you need to search files. To check a string, pipe it togrepwith the-qflag to suppress output:if echo "$full" | grep -q "$sub"; then echo "Found"; else echo "Not found"; fi
Note thatgrepuses regular expressions by default, so special characters in$sub(like.or*) will be interpreted. Usegrep -Ffor fixed-string matching. - Use parameter expansion to test without external commands. Bash can remove a prefix and compare the result:
if [[ "${full#*"$sub"}" != "$full" ]]; then echo "Found"; else echo "Not found"; fi
This removes everything up to and including the first occurrence of$sub. If the result is different from the original, the substring exists. - Handle empty substrings. Be aware that all the above methods will return “Found” if
$subis empty. If you need to treat an empty substring as not found, add a check:if [[ -n "$sub" && "$full" == *"$sub"* ]]; then echo "Found"; else echo "Not found"; fi - Test case sensitivity. By default, all methods are case-sensitive. To make a case-insensitive check with
[[ ]], use thenocasematchoption:shopt -s nocasematch
if [[ "$full" == *"$sub"* ]]; then echo "Found"; else echo "Not found"; fi
shopt -u nocasematch
Forgrep, use the-iflag. - Put it in a reusable function. For scripts that need this check multiple times, define a function:
contains() { [[ "$1" == *"$2"* ]]; }
Then call it like:if contains "$full" "$sub"; then echo "Found"; fi
Common Mistakes
- Forgetting quotes around the substring. If you write
[[ $full == *$sub* ]]without quotes, bash will perform word splitting and globbing on$sub. This breaks if the substring contains spaces or special characters. - Using single brackets
[ ]instead of double[[ ]]. The single bracket does not support the*wildcard pattern matching the same way; it treats*as a literal character. - Expecting
grepto do literal matching by default. Without-F,grepinterprets regex metacharacters. For example,grep "a.c"matches “abc”, not “a.c”. - Ignoring empty substrings. As noted, an empty substring always matches. Decide if that’s the behavior you want.
- Using
echowith strings starting with a dash. If$fullstarts with-nor-e,echomay interpret it as an option. Useprintf '%s' "$full" | grep ...instead.
Tips
- For simple substring checks, prefer
[[ ]]—it’s built into bash, fast, and avoids spawning external processes. - If you need to check if a string starts with a substring, use
[[ "$full" == "$sub"* ]]. To check if it ends with, use[[ "$full" == *"$sub" ]]. - When using
grepin a loop, remember thatgrep -qexits on the first match, which is efficient for large inputs. - If you’re working with arrays or lists, consider using
[[ " ${array[@]} " =~ " $sub " ]]with spaces around elements to avoid partial matches. - Always quote variables in
[[ ]]to prevent word splitting and globbing, even if you think they’re safe.
Troubleshooting
My script says “Not found” but the substring is clearly there. Check for hidden characters like trailing newlines or carriage returns. Use cat -A to see them. Also verify that the substring doesn’t contain spaces that you might have forgotten to quote.
The [[ ]] method fails with special characters like [ or ]. In the pattern, [ starts a character class. To match a literal [, you need to escape it or use grep -F. For example: [[ "$full" == *"["* ]] won’t work as expected because [ is special. Use grep -F or escape: [[ "$full" == *'['* ]].
My script works in the terminal but not in a script file. Ensure the script has a shebang line #!/bin/bash and is executed with bash script.sh or made executable with chmod +x. If you run it with sh script.sh, it might use dash, which doesn’t support [[ ]].
Case-insensitive matching doesn’t work. The shopt -s nocasematch option must be set before the [[ ]] test and unset after. Also note that this option affects all pattern matching in the current shell, so remember to reset it.
Performance is slow when checking many strings. If you’re looping over thousands of strings, the [[ ]] method is fastest. Avoid using grep in a loop if possible; instead, use a single grep with -F and a list of patterns.
Frequently Asked Questions
Can I use contains as a command?
No, contains is not a standard Linux command. You can define a shell function named contains as shown above, but it won’t be available outside your script unless you export it.
How do I check if a string contains one of several substrings?
Use a loop over the substrings, or use a regex alternation with =~: [[ "$full" =~ (sub1|sub2|sub3) ]]. For many substrings, a loop is clearer.
Does [[ ]] work in all versions of bash?
The [[ ]] construct has been available since bash 2.0, but the pattern matching with * works as expected in all modern bash versions (3.x and later). For maximum compatibility, use case.
How do I check if a string does NOT contain a substring?
Simply negate the condition: if [[ "$full" != *"$sub"* ]]; then echo "Not found"; fi. Or use ! grep -q.
Can I use expr to check?
Yes, expr index returns the position of the first character of the substring, but it’s not reliable for multi-character substrings. expr match is better but still limited. Stick with [[ ]] or grep.
What is the difference between [[ ]] and test?
[[ ]] is a bash keyword that supports pattern matching, regex, and no word splitting. test (or [ ]) is an external command (though built into bash) that only supports string comparison, not pattern matching. Use [[ ]] for substring checks.
Related
General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.
More in this bed
- Google Desktop Search Widget on Windows 11
- How to Build a Computer Stand (Saturday Workshop)
- Customize Touch Keyboard Themes in Windows 11
- Excel Pivot Table: Change Multiple Field Settings
- WhatsApp: How to Block Unknown Numbers
- How to Exit Vi in Linux: A Simple Guide