Pattern matching in shell - not full exact pattern - shell

How to do pattern match in shell
if ( $var ~= /abc/)
As we do like the above command in perl.

Using bash :
if [[ $var =~ regex ]]; then ...; fi
or
if [[ $var == *string* ]]; then ...; fi
or if not using bash :
if echo "$var" | grep &>/dev/null regex; then ...; fi
See
http://wiki.bash-hackers.org/syntax/ccmd/conditional_expression
http://mywiki.wooledge.org/BashGuide/Patterns

Related

Match if variable has WORD repeated more than once

I have this variable:
>echo $br_name
srxa wan-a1 br-wan3-xa1 0A:AA:DD:C1:F1:A3 ge-0.0.3 srxa wan-a2 br-wan3-xa2 0A:AA:DD:C1:F2:A3 ge-0.0.3
I am trying to create a conditional where it detects whether ge-0.0.3 is repeated more than 1 time in my variable $br_name
For example:
if [[ $br_name has ge-0.0.3 repeated more than one time ]]
then
echo "ge-0.0.3 is shown more than once"
else
:
fi
Bash's =~ is using extended RE.
[Bash-5.2] % check() { local s='(ge-0\.0\.3.*){2,}'; [[ "$1" =~ $s ]] && echo yes || echo no; }
[Bash-5.2] % check 'xxx'
no
[Bash-5.2] % check 'ge-0.0.3'
no
[Bash-5.2] % check 'ge-0.0.3 ge-0.0.3 '
yes
[Bash-5.2] % check 'ge-0.0.3 ge-0.0.3 ge-0.0.3 '
yes
You can use grep -o to print only the matched phrase. Also use -F to make sure that it matches literal characters instead of a regex where . and - are special
if [[ $(echo "$br_name" | grep -Fo ge-0.0.3 | wc -l) -gt 1 ]]; then
echo "ge-0.0.3 is shown more than once"
else
echo "only once"
fi
For more complex patterns of course you can drop -F and write a proper regex for grep
simple word
If your word would be "easy", you can detect the occurrences count with:
echo "123 123 123" | sed "s/123 /123\n/g" | wc -l
In which the word is replace for the same but with \n and then wc count the lines
or you can try one of these:
Count occurrences of a char in a string using Bash
How to count number of words from String using shell
complex
Since your word is "complex" or you will want a pattern, you will need regex:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
https://linuxconfig.org/advanced-bash-regex-with-examples
script.sh
count=0
for word in $1; do
if [[ "$word" =~ .*ge-0\.0\.3.* ]]
then
count=$(($count+1))
fi
done
if [ "$count" -gt "1" ];
then
echo "ge-0.0.3 is shown more than once"
else
if [ "$count" -eq "0" ];
then
echo "ge-0.0.3 is not shown"
else
echo "ge-0.0.3 is shown once"
fi
fi
execution
bash script.sh "srxa wan-a1 br-wan3-xa1 0A:AA:DD:C1:F1:A3 ge-0.0.3 srxa wan-a2 br-wan3-xa2 0A:AA:DD:C1:F2:A3 ge-0.0.3"
grep
With grep you can get the ocurrence count
ocurrences=( $(grep -oE '(ge-0\.0\.3)' <<<$1) )
ocurrences_count=${#ocurrences[*]}
echo $ocurrences_count
Assuming you want to do a literal string match on whole words, not substrings, then this might be what you want:
$ if (( $(grep -oFw 'ge-0.0.3' <<<"$br_name" | wc -l) > 1 )); then echo 'yes'; else echo 'no'; fi
yes

Patter matching variable and string

bash script
Hi! I would like to make a bash script that contolli if the content of a var variable does pattern matching with the string ending with ABC?
You can use the bash builtins:
# with glob patterns
if [[ $var == *ABC ]]; then echo "$var ends with ABC"; fi
# with regular expression
if [[ $var =~ ABC$ ]]; then echo "$var ends with ABC"; fi
You are almost there
var="hellowordABC"
echo $var | grep ".*ABC$"
Or using builtin conditions
[[ $var =~ ABC$ ]] && echo "var ends with ABC"

SED replace in bash between round brackets

I want to use sed to check if some string match to a pattern and then save that match into a variable:
function tst2(){
string='cms(1.2;1.5;1.3)'
regex='cms\(.*\)'
echo -e $string
if [[ $string =~ $regex ]]
then
myVar=$(echo -e $string | sed "s/cms\(.*\)/\1/g")
echo $myVar
else
echo "too badd!!!"
fi
}
Console output:
[user#home~]$ tst2
cms(1.2;1.5;1.3)
(1.2;1.5;1.3)
I would like myVar to become "1.2;1.5;1.3" (without the round brackets)
This is a faster way without having to use sed. It uses the bash builtin BASH_REMATCH variable filled when the =~ operator is used:
function tst2(){
string='cms(1.2;1.5;1.3)'
regex='cms\((.*)\)'
echo -e $string
if [[ $string =~ $regex ]]
then
echo ${BASH_REMATCH[1]}
else
echo "too badd!!!"
fi
}
myVar=$(expr $string : $regex)
This will do what you want (using the shell's builtin expr). You need to adjust your regex though, to:
regex='cms(\(.*\))'
That matches the brackets yet doesn't include them in the result.

case insensitive check in if loop using regex in 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] ]]

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