How can I compare two similar strings with a wildcard in bash? - bash

How can I best compare two similar strings in bash?
I want to compare 1.1.1.1:1000 to 1.1.1.1 and find it to be a match.
1.1.1.1:1000 1.1.1.1 MATCH
1.1.1.2:1000 1.1.1.1 NO MATCH
Here's a simple script illustrating the challenge:
#!/bin/sh
IPONE="1.1.1.1:1000"
IPTWO="1.1.1.1"
if [[ "$IPONE" == "$IPTWO*" ]] ; then
echo "$IPONE $IPTWO Match"
else
echo "$IPONE $IPTWO ERROR"
fi

If I understand correctly, you want to compare, for an exact match, the part before the colon. In that case:
if [[ "${IPONE%%:*}" == "${IPTWO%%:*}" ]] ; then
echo "$IPONE $IPTWO Match"
else
echo "$IPONE $IPTWO ERROR"
fi

If you want to use glob-syntax, then you need to use =~ instead of == in your [[ ... ]], and you can't have the second parameter quoted. So it should like this:
if [[ "$IPONE" =~ $IPTWO* ]]; then
If you need to have the second parameter quoted, just do this:
if [[ "$IPONE" =~ "$IPTWO"* ]]; then
If you need to find a match that matches a string up to the last of a delimiter, in this case ., then try this:
if [[ "$IPONE" =~ ([0-9]|\.){3}[0-1]* ]]; then

I think POSIX substring parameter expansion, may be have trick
#!/bin/bash
IPONE="1.1.1.1:1000"
IPTWO="1.1.1.1"
if test "${IPONE#*$IPTWO}" != "$IPONE"
then
echo "$IPONE $IPTWO Match"
else
echo "$IPONE $IPTWO ERROR"
fi
OR
IPONE="1.1.1.1:1000"
IPTWO="1.1.1.1"
if [[ "${IPONE}" == *$IPTWO* ]]
then
echo "$IPONE $IPTWO Match"
else
echo "$IPONE $IPTWO ERROR"
fi

Related

Check if multiple 'If Statements failed

I'm working on a script that checks (with If statements) if a variable contains a specific character. If a character is found the script executes some code. If a certain character cannot be found, the script will go into another If Statement to check if the variable contains another specific character, and so on.
this all works perfectly fine.
But I need the script to tell me if none of the characters are found, but i'm having some trouble accomplishing this goal. the script looks like this.
if [[ "$results" == *"specific character"* ]]; then
do something.
fi
if [[ "$results" == *"specific character"* ]]; then
do something.
fi
if [[ "$results" == *"specific character"* ]]; then
do something.
fi
If all these If Statements cannot find their character I need the script to echo that these characters are not found.
I tried to put a If/else statement around all the other If statements, but this did not work for me.
if [[ ]]; then
if [[ "$results" == *"specific character"* ]]; then
do something.
fi
if [[ "$results" == *"specific character"* ]]; then
do something.
fi
if [[ "$results" == *"specific character"* ]]; then
do something.
fi
else
echo "characters are not found."
I can't seem to get it to work. Can somebody give me a push in the right direction?
Kind Regards,
Sleek
Use a case statement:
case "$results" in
*c*) do something;;
*d*) do something;;
*e*|*f*) do something
do another thing;;
*) echo "characters are not found.";;
esac
You could just set a variable in the if bodies and check whether it's set or not lateron, like so:
...
if [[ "$results" == *"specific character"* ]]; then
foundsmth=1
fi
if [[ -z ${foundsmth} ]] ; then
# nothing found
fi
Another solution would be to use regular expressions in combination with a switch-case construction as explained here.
For your if surrounding the individual if statements, you could use a regex:
if [[ $str =~ [abc] ]]; then
if [[ "$str" == *"a"* ]]; then
echo "a"
fi
if [[ "$str" == *"b"* ]]; then
echo "b"
fi
if [[ "$str" == *"c"* ]]; then
echo "c"
fi
else
echo "None of those characters are in str"
fi
I usually prefer a case like Dennis.
Since you already have it written as if's, you could use a compound if/elif/else, so long as it's ok to short-circuit out before checking them all.
if [[ "$results" == *"specific character"* ]]
then : do something.
elif [[ "$results" == *"specific character"* ]]
then : do something.
elif [[ "$results" == *"specific character"* ]]
then : do something.
else echo "characters are not found."
fi
On the other hand, if you need to check them ALL, whether or not any are found along the way, you're going to need mju's flag variable.
found=0;
if [[ "$results" == *"specific character"* ]]
then ((found++)); : do something.
fi
if [[ "$results" == *"specific character"* ]]
then ((found++)); : do something.
fi
if [[ "$results" == *"specific character"* ]]
then ((found++)); : do something.
fi
((found)) || echo "characters are not found."

Bash: why does comparison precedence matter with wildcards?

Is the == functioning like an IN operator when the test string contains wildcards? It's very magical...
example1:
string='My long string';
if [[ $string == *"My long"* ]]; then echo "It's there!"; fi
output:
It's There
example2:
if [[ *"My long"* == $string ]]; then echo "It's there!"; fi
No output.
That's how [[ ]] was designed to work. It's in the manual:
When the ‘==’ and ‘!=’ operators are used, the string to the right of the operator is considered a pattern and matched according to the rules described below in Pattern Matching.
Glob pattern only works on right hand side of comparison that's why
if [[ *"My long"* == $string ]]; then echo "It's there!"; fi
will fail.
Even this won't work:
[[ *"My long"* == "My long" ]] && echo "It's there!"
But this will work:
[[ "My long" == *"My long"* ]] && echo "It's there!"
It's there!
If you are asking how this is working:
string='My long string';
if [[ $string == *"My long"* ]]; then echo "It's there!"; fi
Then it is working due to use of glob matching on your RHS pattern that uses *
Which means match anything before and after literal text "My long" and since your input does contain "My long" hence match succeeds.

Bash: If line begins with >

I want an if/then statement in Bash and I can't seem to get it to work. I would like to say "If the line begins with > character, then do this, else do something else".
I have:
while IFS= read -r line
do
if [[$line == ">"*]]
then
echo $line'first'
else
echo $line'second'
fi
done
But it isn't working.
I also tried to escape the ">" by saying:
if [[$line == ^\>*]]
Which didn't work either.
Both ways I am getting this error:
line 27: [[>blah: command not found
Suggestions?
Spaces are needed inside [[ and ]] as follows:
if [[ "$line" == ">"* ]]; then
echo "found"
else
echo "not found"
fi
This attempt attempt uses a regex:
line="> line"
if [[ $line =~ ^\> ]] ; then
echo "found"
else
echo "not found"
fi
This one uses a glob pattern:
line="> line"
if [[ $line == \>* ]] ; then
echo "found"
else
echo "not found"
fi
Spacing is important.
$ [[ ">test" == ">"* ]]; echo $?
0
$ [[ "test" == ">"* ]]; echo $?
1
if grep -q '>' <<<$line; then
..
else
..
fi
using grep is much better :)

Validating filename in Bash

I want to validate a file name in bash to make sure that I don't have this '[]' character in it
I have this :
if ! [[ $filename=~ ^[a-zA-Z]+$ ]]; then
echo 'Wrong filename input' >&2
exit 1
fi
but I want explicitly avoid [] and allow other special characters.
any advice?
Thanks.
Use spaces around =~ operator:
[[ ! "$filename" =~ ^[a-zA-Z]+$ ]] && echo "bad filename" || echo "its good"
OR your own script:
if [[ ! "$filename" =~ ^[a-zA-Z]+$ ]]; then
echo 'Wrong filename input' >&2
exit 1
fi
Update:
If you want to explicitly avoid only [ and ] then following check is better:
if [[ "$filename" == *[]\[]* ]]; then
echo 'Wrong filename input' >&2
exit 1
fi

Check input consists only of numeric characters in shell script

I need to check that the input consists only of numeric characters. I have the code below, but it didn't work properly.
if [[ $1 =~ [0-9] ]]; then
echo "Invalid input"
fi
It should give true only for 678686 not for yy66666.
How about this:-
re='^[0-9]+$'
if ! [[ $Number =~ $re ]] ; then
echo "error: Invalid input" >&2; exit 1
fi
or
case $Number in
''|*[!0-9]*) echo nonnumeric;;
*) echo numeric;;
esac
Try using start/end anchors with your pattern. If you don't, the match succeeds with a part of a test string. Don't forget that you have to use a pattern matching the complete test string if you follow this suggestion.
if [[ $1 =~ ^[0-9]+$ ]]; then
echo "Invalid input"
fi
Check out this SO post for more details.

Resources