
Sometimes in Linux scripts you want to know if a text string contains a specific smaller string. There are many ways to do this. We show you some simple and reliable techniques.
Why is it useful?
Searching a string for a smaller substring is a common requirement. An example would be reading text from a file or human input and searching the string for a specific substring so that your script can decide what to do next. It could be looking for a tag or device name in a configuration file or a command string on a user input line.
Linux users are blessed with a plethora of utilities for manipulating text. Some are built into the Bash shell, others are provided as stand-alone utilities or applications. There is a reason why Unix-derived operating systems have abundant string manipulation capabilities.
Some things that appear to be files are not simple files. They are special files representing things like hardware devices and system information sources. The abstraction performed by the operating system gives them the appearance and characteristics of files. You can read information from them, as text of course, and in some cases write to them, but they are not ordinary files.
The text is also used as input and output for commands in a terminal window. This allows input and output redirection and pipelining. That functionality supports the ability to chain Linux scripts, passing the output of one command as input to the next.
Regardless of its origins, searching the text we receive for a meaningful word, command, tag, or some other indicator is a standard part of handling text-based data. Here is a collection of simple techniques that you can include in your own scripts.
Find substrings with Bash Builtins
The double brackets”[[...]]
The string comparison test can be used in if
instructions to determine if a string contains another string.
Copy this script into an editor and save it to a file called “double.sh”.
#!/bin/bash if [[ "monkey" = *"key"* ]]; then echo "key is in monkey" else echo "key is not in monkey" fi
You will need to make the script executable with the chmod
domain. This is a step that is always required to make any script executable. You will need to do this each time you create a script file. Substitute the appropriate script name in each case.
chmod +x double.sh
Let’s run the script.
./double.sh
This works because the asterisk” *
” represents any sequence of characters, even without characters. If the “key” of the substring is found within the target string, with or without leading or trailing characters, the test will return true.
In our example, there are characters in front of the substring. These correspond to the first asterisk. There are no letters after the substring, but since an asterisk also does not match any characters, the test still passes.
For more flexibility, we can modify our script to handle variables instead of literal strings. This is the “double2.sh” script.
#!/bin/bash string="Monkey" substring="key" if [[ $string = *$substring* ]]; then echo "$substring was found in $string" else echo "$substring was not found in $string" fi
Let’s see how that works.
./double2.sh
This works the same way, with the advantage that we can use variable names instead of literal strings. Turning our small solution into a function will provide the most flexibility.
This is the “double3.sh” script.
#!/bin/bash shopt -s nocasematch string="Monkey" substring="Key" capital="London" check_substring () { if [[ $1 = *$2* ]]; then echo "$2 was found in $1" else echo "$2 was not found in $1" fi } check_substring "Monkey" "key" check_substring $string $substring check_substring $string "banana" check_substring "Wales" $capital
we call our check_substring
function using a combination of variables and literal strings. We use shopt
with his -s
(set) option to configure nocasematch
so that the matches are not case sensitive.
Is that how it works.
./double3.sh
We can use the trick of wrapping the substring in asterisks in case
statements, too. This is “case.sh”.
#!/bin/bash shopt -s nocasematch string="Wallaby" substring="Wall" case $string in *$substring*) echo "$substring was found in $string" ;; *) echo "Nothing matched: $string" ;; esac
Wearing case
statements instead of very long if
Declarations can make scripts easier to read and debug. If I needed to check if a string contained one of many possible substrings, the case
statement would be the best option.
./case.sh
The substring is found.
Find substrings with grep
Beyond Bash’s built-in features, the first text search tool you’re likely to come across is grep
. we can use grep
The innate ability to search a string within a string to find our substrings.
This script is called “subgrep.sh”.
#!/bin/bash string="porridge pot" substring="ridge" if $(echo $string | grep -q $substring); then echo "$substring was found in $string" else echo "$substring was not found in $string" fi
The script uses echo
to send the string to grep
, which searches for the substring. we are using the -q
option (silent) to stop grep
writing anything to standard output.
If the result of the commands in parentheses “(...)
” equals zero, it means a match was found. because zero equals true
in bash, the if
the statement is met and then
the clause is executed.
Let’s see what your output is.
./subgrep.sh
Find substrings with sed
we can use sed
to find a substring, too.
By default, sed
prints all text that is fed into it. Using sed -n
prevents this. The only lines that are printed are matching lines. This expression will print any lines that match or contain the value of $substring.
"/$substring/p"
We feed the value of $string
within sed
using a redirect here, <<<
. This is used to redirect values to a command in the current shell. It doesn’t invoke a sublayer like a pipeline would.
First -n
is the proof. return true
if the output of sed
command is nonzero. The only way the output of sed
can be nonzero if a matching line was found. If that’s the case, $substring
must have been found in $string
.
This is “subsed.sh”.
#!/bin/bash string="Sweden" substring="eden" if [ -n "$(sed -n "/$substring/p" <<< $string)" ]; then echo "$substring was found in $string" else echo "$substring was not found in $string" fi
We get the expected response when we run the script.
./subsed.sh
We can test the logic of the script by editing the value of $substring
for the comparison to fail.
./subscribed.sh
stop looking i found it
Other tools can find substrings, like awk
Y Perl
but a simple use case like finding a substring doesn’t guarantee its additional functionality or added complexity. In particular, using Bash’s built-in functions to search for substrings is fast, simple, and requires no external tools.
RELATED: How to use case statements in Bash scripts