Bash is a great program language to quickly write scripts and tasks. But there is one particular thing Bash isn't well suited for: String comparisons (I'd use Perl for this). But with a little bit of Bash magic, this works well, too.
There are string comparisons available using test. From the test man page:
STRING1 = STRING2
the strings are equal
STRING1 != STRING2
the strings are not equal
In general string comparisons work:
ck@mintp ~ $ var="linux"
ck@mintp ~ $ if [[ "$var" = "linux" ]]; then echo "yes"; else echo "no"; fi
yes
But what if one wants to know if a part of a string matches another string, kind of as a regular expression?
ck@mintp ~ $ var="linu"
ck@mintp ~ $ if [[ "$var" = "linux" ]]; then echo "yes"; else echo "no"; fi
no
Because the stored variable $var only contains a part of the string ("linu"), the string comparison does not work. test tries to compare both $var and the string and only if they match 100%, then the test would return true (or in this case "yes").
When running Bash in verbose mode (-x), the comparison can be seen:
ck@mintp ~ $ var="linu"
ck@mintp ~ $ set -x
set -x
ck@mintp ~ $ if [[ "$var" = "linux" ]]; then echo "yes"; else echo "no"; fi
+ [[ linu = \l\i\n\u\x ]]
+ echo no
no
The verbose mode clearly shows that [[ linu = \l\i\n\u\x ]] will not match (the backslashes can be ignored for the human eye).
Bash however adds another feature to test: The regular expression hyphen (~). By using it in the test condition, Bash will do a regular expression matching.
But use caution! The position of the variable is highly important. If the variable $var is used on the left side, there will be no match:
ck@mintp ~ $ var="linu"
ck@mintp ~ $ if [[ "$var" =~ "linux" ]]; then echo "yes"; else echo "no"; fi
no
But if the variable is on the right side of the comparison, the regular match should work:
ck@mintp ~ $ var="linu"
ck@mintp ~ $ if [[ "linux" =~ "$var" ]]; then echo "yes"; else echo "no"; fi
yes
Important note: The regular expression hyphen (~) only works in Bash and in test conditions with double brackets [[ condition ]].
Now to the next problem: Case insensitive matching!
The previous tests always used lowercase letters and string matching worked. But what if the variable contains a mix of lowercase and uppercase letters?
ck@mintp ~ $ var="LinuX"
ck@mintp ~ $ if [[ "linux" =~ "$var" ]]; then echo "yes"; else echo "no"; fi
no
Because of the upperscale L and X in "LinuX", the variable doesn't match "linux" anymore - even with regular expression.
To handle this, Bash needs to be told to switch into "nocasematch" mode. This can be done using the shopt command (a Bash specific command to set or unset Shell options, see Shopt on Cyberciti):
ck@mintp ~ $ var="LinuX"
ck@mintp ~ $ shopt -s nocasematch; if [[ "linux" =~ "$var" ]]; then echo "yes"; else echo "no"; fi
yes
What about just a part of the full string?
ck@mintp ~ $ var="LiN"
ck@mintp ~ $ shopt -s nocasematch; if [[ "linux" =~ "$var" ]]; then echo "yes"; else echo "no"; fi
yes
The condition now finally returns "yes" because a case insensitive regular expression matches.
But Bash can do even more than that; it can also use POSIX regular expressions - at least to a certain extend. Let's use above string comparison with multiple comparisons. The $var variable should be compared against multiple options:
ck@mintp ~ $ var="linux ubuntu"
ck@mintp ~ $ shopt -s nocasematch; if [[ ${var} =~ ^(linux|ubuntu|sles|debian|rhel) ]]; then echo "yes"; else echo "no"; fi
yes
The condition returns yes, as either "linux" and "ubuntu" strings were found.
If we use a different Operating System as string value for $var, it won't match:
ck@mintp ~ $ var="windows 2019"
ck@mintp ~ $ shopt -s nocasematch; if [[ ${var} =~ ^(linux|ubuntu|sles|debian|rhel) ]]; then echo "yes"; else echo "no"; fi
no
No comments yet.
AWS Android Ansible Apache Apple Atlassian BSD Backup Bash Bluecoat CMS Chef Cloud Coding Consul Containers CouchDB DB DNS Database Databases Docker ELK Elasticsearch Filebeat FreeBSD Galera Git GlusterFS Grafana Graphics HAProxy HTML Hacks Hardware Icinga Influx Internet Java KVM Kibana Kodi Kubernetes LVM LXC Linux Logstash Mac Macintosh Mail MariaDB Minio MongoDB Monitoring Multimedia MySQL NFS Nagios Network Nginx OSSEC OTRS Office PGSQL PHP Perl Personal PostgreSQL Postgres PowerDNS Proxmox Proxy Python Rancher Rant Redis Roundcube SSL Samba Seafile Security Shell SmartOS Solaris Surveillance Systemd TLS Tomcat Ubuntu Unix VMWare VMware Varnish Virtualization Windows Wireless Wordpress Wyse ZFS Zoneminder