Patter matching variable and string - bash

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"

Related

Bash - Comparing a string to an array that contains wildcards?

I have an array of possible file extensions, which contains some wild cards e.g.:
FILETYPES=("DBG" "MSG" "OUT" "output*.txt")
I also have a list of files, which I am grabbing the file extension from. I then need to compare the extension with the array of file extensions.
I have tried:
if [[ ${EXTENSION} =~ "${FILETYPES[*]}" ]]; then
echo "file found"
fi
if [[ ${EXTENSION} == "${FILETYPES[*]}" ]]; then
echo "file found"
fi
and
if [[ ${EXTENSION} =~ "${FILETYPES[*]}" ]]; then
echo "file found"
fi
But to no avail
I tried:
if [[ "${FILETYPES[*]}" =~ ${EXTENSION} ]]; then
echo "file found"
fi
However, it ended up comparing "txt" to "output*.txt" and concluding it was a match.
FILETYPES=("DBG" "MSG" "OUT" "output*.txt") First of all, avoid ALL_CAPS variable names except if these are meant as global environment variables.
"output*.txt": is ok as a globing pattern, for bash test [[ $variable == output*.txt ]] for example. But for Regex matching it needs a different syntax like [[ $variable =~ output.*\.txt ]]
"${FILETYPES[*]}": Expanding this array into a single_string was mostly a good approach, but it needs clever use of the IFS environment variable to help it expands into a Regex. Something like IFS='|' regex_fragment="(${array[*]})", so that each array entry will be expanded, separated by a pipe | and enclosed in parenthesis as (entry1|entry2|...).
Here is an implementation you could use:
textscript.sh
#!/usr/bin/env bash
extensions_regexes=("DBG" "MSG" "OUT" "output.*\.txt")
# Expands the extensions regexes into a proper regex string
IFS='|' regex=".*\.(${extensions_regexes[*]})"
# Prints the regex for debug purposes
printf %s\\n "$regex"
# Iterate all filenames passed as argument to the script
for filename; do
# Compare the filename with the regex
if [[ $filename =~ $regex ]]; then
printf 'file found: %s \n' "$filename"
fi
done
Sample usage:
$ touch foobar.MSG foobar.output.txt
$ bash testscript.sh *
.*\.(DBG|MSG|OUT|output.*\.txt)
file found: foobar.MSG
file found: foobar.output.txt
You cannot directly compare a string with an array. Would you please try something like:
filetypes=("DBG" "MSG" "OUT" "output*.txt")
extension="MSG" # example
match=0
for type in "${filetypes[#]}"; do
if [[ $extension = $type ]]; then
match=1
break
fi
done
echo "$match"
You can save looping with regex:
pat="^(DBG|MSG|OUT|output.*\.txt)$"
extension="output_foo.txt" # example
match=0
if [[ $extension =~ $pat ]]; then
match=1
fi
echo "$match"
Please note the expressions of regex differ from wildcards for globbing.
As a side note, we conventionally do not use uppercases for user variables to avoid conflicts with system variables.

Shell If else with regex

I am using shell to simple String regex match. Here is my shell
#!/bin/sh
MSG="ANK"
PATTERN="([A-Z]{3,5}[-][0-9]{2,5})"
if [ "$MSG" =~ "$PATTERN" ]; then
echo "MATCHED";
else
echo "not";
fi
It is giving error
abc.sh: 6: [: ANK: unexpected operator
How should I fix this?
Making the changes proposed by several contributors in the comments yields:
#!/bin/bash
MSG="ANK"
PATTERN="([A-Z]{3,5}[-][0-9]{2,5})"
if [[ "$MSG" =~ $PATTERN ]]; then
echo "MATCHED";
else
echo "not";
fi
Note the change to bash, the change to [[ and removal of the quotation marks around $PATTERN.

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.

Pattern matching in shell - not full exact pattern

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

Regarding Bash substring comparison

I try to test if a string starts with a certain prefix. But my script seems not work (I would expect the "if" branch will not get run). Can some Bash expert help to take a look? thanks!
Here is my code and test result:
$ cat testb.bash
#!/bin/bash
my_var="abcdefg";
if [[ "${my_var:0:5}"=="order" ]]; then
echo "value of my_var is ${my_var}.";
fi;
if [[ "${my_var:0:5}" -eq "order" ]]; then
echo "value of my_var is ${my_var}.";
fi;
if [ "${my_var:0:5}"="order" ]; then
echo "value of my_var is ${my_var}.";
fi;
$ bash -x testb.bash
+ my_var=abcdefg
+ [[ -n abcde==order ]]
+ echo 'value of my_var is abcdefg.'
value of my_var is abcdefg.
+ [[ abcde -eq order ]]
+ echo 'value of my_var is abcdefg.'
value of my_var is abcdefg.
+ '[' abcde=order ']'
+ echo 'value of my_var is abcdefg.'
value of my_var is abcdefg.
$
Whitespace is significant in this case. As you can see in the -x output, it understands the first condition as
[[ -n "${my_var:0:5}==order" ]]
Moreover, to test for a prefix, you can use a pattern:
[[ $my_var == order* ]]
To test the existence of substring, you can use either of these:
if [[ "$j" =~ string1 ]]; then
if [[ $j == *string1* ]]; then
In your particular case, you miss a space surounding ==, so instead of
if [[ "${my_var:0:5}"=="order" ]]; then
it should be
if [[ "${my_var:0:5}" == "order" ]]; then
^ ^
Finally, note that your condition was evaluated as true because it was evaluating if [ "string" ], which is true if string is not empty:
$ [ "a" ] && echo "yes"
yes
Test
$ cat a
#!/bin/bash
my_var="abcdefg";
if [[ "${my_var:0:5}" == "order" ]]; then
echo "value of my_var is ${my_var}."
elif [[ "${my_var:0:5}" == "abcde" ]]; then
echo "yeahaa"
else
echo "is not"
fi
$ ./a
yeahaa
Ok, i tested your code, you shoud such as the following code:
prefix="pre_order";
pre="pre_"
len=${#pre}
echo $len
if [[ "${prefix:0:len}" == "blahvlah" ]] ; then
echo "dddd"
fi;
Notes:
use == for string comparation
for ${} you should initilize a string variable before ${}
use len=${#pre} for lenght of string.
A POSIX-compliant way to test for a prefix is to attempt to remove the prefix, and compare the result to the original string. If the two are the same, the prefix is not present, the removal fails, and the expression expands to the original string.
prefix=foo
string=foobar
if [ "${string#$prefix}" = "$string" ]; then
printf "$string does not start with $prefix\n"
else
printf "$string starts with $prefix\n"
fi

Resources