case insensitive check in if loop using regex in shell - shell

I want to check the following condition, but it should be case insensitive.
if [ "SPP" == $1 ]
Is there anyway I can do it using regex.

You can also do the following:
#!/bin/bash
myParam=`echo "$1" | tr 'a-z' 'A-Z'`
if [ "SPP" == "$myParam" ]; then
echo "Is the same"
else
echo "It is not the same"
fi
This script will automatically converts user input to uppercase before making any string comparison. By doing so, you will not have to use regex for case insensitive string comparison.
Hope it helps.

Better late than never...
If that's ksh93, use the ~(i:...) case-insensitive globbing sub-pattern:
if [[ $1 == *~(i:spp)* ]]; then
: matched.
fi
For ksh88 (also the ksh clones), use an intermediary variable typeset -u'd to force upper-case:
typeset -u tocheck=$1
if [[ $tocheck == *SPP* ]]; then
: matched
fi

You can use:
shopt -s nocasematch
For case insensitive matching in BASH.
Alternatively this should also work:
[[ "$1" == [sS][pP][pP] ]]

Related

How can I check if a variable is contains only letters

I tried to check the following case:
#!/bin/bash
line="abc"
if [[ "${line}" != [a-z] ]]; then
echo INVALID
fi
And I get INVALID as output. But why?
It's no check if $line contains only a characters in the range [a-z] ?
Use the regular expression matching operator =~:
#!/bin/bash
line="abc"
if [[ "${line}" =~ [^a-zA-Z] ]]; then
echo INVALID
fi
Works in any Bourne shell and wastes no pipes/forks:
case $var in
("") echo "empty";;
(*[!a-z]*) echo "contains a non-alphabetic";;
(*) echo "just alphabetics";;
esac
Use [!a-zA-Z] if you want to allow upper case as well.
Could you please try following and let me know if this helps you.
line="abc"
if echo "$line" | grep -i -q '^[a-z]*$'
then
echo "MATCHED."
else
echo "NOT-MATCHED."
fi
Pattern matches are anchored to the beginning and end of the string, so your code checks if $line is not a single lowercase character. You want to match an arbitrary sequence of lowercase characters, which you can do using extended patterns:
if [[ $line != #([a-z]) ]]; then
or using the regular-expression operator:
if ! [[ $line =~ ^[a-z]+$ ]]; then # there is no negative regex operator like Perl's !~
Why? Because != means "not equal", thats why. You tell bash to compare abc with [a-z]. They are not equal.
Try echo $line | grep -i -q -x '[a-z]*'.
The flag -i makes grep case insensitive.
The flag -x means match the whole line.
The flag -q means print nothing to stdout, just return 1 or 0.

How to convert test operator from bash to sh?

I have next string comparison in bash:
if [[ $1 == "/"* ]]; then echo YES; else echo "$1"; fi
How to do same in sh?
You could do it with a case statement.
case $1 in
/*) echo YES;;
*) echo $1
esac
The direct translation would be if [ "$1" = "/*" ], but it wouldn't work because sh doesn't support glob matches there. You'd need to invoke an external command like grep.
if printf '%s\n' "$1" | grep -e '^/' >/dev/null 2>&1; then
...
fi
This would be shorter with grep -q, but if you don't have bash then you may not have grep -q either.
The case statement handles this elegantly.
case $1 in
'/'* ) echo YES;;
*) echo "$1";;
esac
The lack of quoting before in and the general syntax with the double semicolons and unpaired right parentheses is jarring to the newcomer, but you quickly get used to it. It's quite versatile and much under-appreciated.
If you insist on using [ you could perhaps do something like
if temp=${1#?}; [ "${1%$temp}" -eq '*' ]; then
...
which uses a couple of parameter expansions to extract the first character of the variable; but case has glob pattern matching built in, so it's considerably more readable.
If you would like to match a pattern, or regex in if statements if sh or fish you can use
if echo "$1" | grep -q ^/; then echo yes; else echo "$1"; fi

Match string to multiple globs in Bash

I'm trying to simplify my Bash 4 script. I'm reading lines from a file and I want to exclude lines matching certain substrings:
while read p; do
if [[ $p != *-ext ]]; then
if [[ $p != *-backend ]]; then
if [[ $p != *-vip ]]; then
echo $p
fi
fi
fi
fi
done < $hostsfile
So if the line does NOT end with -ext or -backend or -vip then print it. What's an easier way (one-liner that doesn't chain &&'s) to accomplish this?
Use an extended pattern. This requires the extglob option be enabled, but that is (temporarily) enabled by default for the RHS of the != operator inside [[ in bash 4.2 or later.
shopt -s extglob # if necessary
if [[ $p != *-#(backend|vip|ext) ]]; then
An equivalent using regular expressions would be
if ! [[ $p =~ (backend|vip|ext)$ ]]; then
No additional options need to be set, but a regular expression isn't implicitly anchored, so you don't need to match the beginning of the string like *- does in the pattern, but you do need to explicitly match the end of the string with $. Also, there is no doesn't-match regular-expression operator (like !~ in Perl), so you need to use =~ and negate the exit status of the command.
Adding a POSIX-compliant option (portable to /bin/sh) to the otherwise very good answer already present:
case $p in *-backend|*-vip|*-ext) : ;; *) echo "$p" ;; esac
Split out onto multiple lines, that would look like:
case $p in
*-backend|*-vip|*-ext)
:
;;
*)
echo "$p"
;;
esac
...that is to say, we're running the : command (shorthand for true) if any of the patterns is matched, and our echo otherwise.

How to test if a command is a shell reserved word?

I am writing a bash script and I would like to verify if a string is a shell reserved word (like if, for, alias, etc...).
How can I do this?
#!/bin/bash
string="$1"
if [[ $(type "$string" 2>&1) == "$string is a shell"* ]]; then
echo "Keyword $string is reserved by shell"
fi
If you want only the shell keywords, then:
#!/bin/bash
string="$1"
[[ $(type -t "$string" 2>&1) == "keyword" ]] && echo reserved || echo not reserved
builtins won't pass this test (only keywords).
A way of doing this with possibility of extending in various cases:
#!/bin/bash
string="$1"
checkfor=('keyword' 'builtin')
for ((i=0;i<${#checkfor[#]};i++))
do
[[ $(type -t "$string" 2>&1) == "${checkfor[$i]}" ]] && reserved=true && break || reserved=false
done
[[ $reserved == true ]] && echo reserved || echo not reserved
command, hash, alias, type etc.. (builtins) will pass the above test as well as keywords.
You can add other possible test conditions by adding an element into the array checkfor:
checkfor=('keyword' 'builtin' 'file' etc...)

Compare bash variable

I need help with how to compare bash variable to a specific format.
i will read user input with read command
for example:
MyComputer:~/Home$ read interface
eth1
MyComputer:~/Home$ echo $interface
eth1
Now i need to check if "$interface" variable with IF loop(it should have "eth" in beginning and should contains numbers 0-9):
if [[ $interface=^eth[0-9] ]]
then
echo "It looks like an interface name"
fi
Thanks in advance
You can use regular expressions for this:
if [[ $interface =~ ^eth[0-9]+$ ]]
then
...
fi
You can use bash's globs for this:
if [[ $interface = eth+([[:digit:]]) ]]; then
echo "It looks like an interface name"
fi
(avoiding regexps removes one problem). Oh, and mind the spaces around the = sign, and also before and after [[ and ]].
You could use bash V3+ operator =~ as Andrew Logvinov said :
[[ $interface =~ ^eth[0-9]+$ ]] && # ...
Or :
if [[ $interface =~ ^eth[0-9]+$ ]]; then
# ...
fi
Otherwise, you could use too egrep or grep -E (which is useful with older shells like sh...) :
echo "$interface"|egrep "^eth[0-9]+$" > /dev/null && # ...
Or :
if echo "$interface"|egrep "^eth[0-9]+$" > /dev/null; then
# ...
fi

Resources