1

I have been driving myself mad on this. I just don't see why it doesn't work when bash variables are untyped. There should be no reason why not.

pat1=`. $NVM_DIR/nvm.sh && nvm ls | sed 's/\x1b\[[^\x1b]*m//g' | sed -e 's/[[:alpha:]|\/\)\-\>\(|[:space:]]//g' | sed 's/[-|\*]//g' | sed '/^$/d'`
pat2=`. $NVM_DIR/nvm.sh && nvm ls node | head -1 | awk '{print $2}' | cut -d v -f2`

these expand to:

~$ echo $pat1
9.5.0
9.5.0
9.5
9.5.0
4.8.7
6.12.3
8.9.4

~$ echo $pat2
9.5.0

So I want to check if the string found in $pat2 is in $pat1 string. however it does not find it even though it clearly is in the pattern 3 times at least.

Checking for the pattern with a test like:

case "$pat1" in
  *$pat2*) 
    echo 'match'
    ;;
  *)
    echo 'nomatch'
    ;;
esac

this gives:

~$ ./test.sh 
nomatch

another test:

if [[ "$pat1" =~ "$pat2" ]]; then 
  echo 'match'
else 
  echo 'nomatch'
fi

again fails:

~$ ./test.sh
nomatch

Even tried some janky hacky method to no avail,

echo $pat1 | grep "$pat2" > /dev/null 
if [ $? -eq 0 ]; then
  echo "matched"
else
  echo "nomatch"
fi

gives the result:

~$ ./test.sh
grep: brackets ([ ]) not balanced
nomatch

Been pulling my hair out today working on this. This must be due to the fact that both variables are command substitutions, it leads me to believe it is comparing the actual commands themselves rather than their output stored in the variables. So even though they echo the output, i think it may be comparing the string of the commands itself.

am I wrong? can anyone explain why this fails to match and if its possible with bash to compare the output of two commands in a string/sub-string type of comparison?

5
  • 1
    To match multiple patterns in case it's pat1|pat2|pat3). Why do you think patterns separated by newlines would work? Commented Feb 8, 2018 at 3:05
  • @Barmar I tested this as well by adding | tr -d '/n' to the $pat1 command, however even that fails to match anything. I am not trying to match multiple patterns, maybe i am misunderstanding what you are saying. I am trying to see if the 9.5.0 exists in the list output by $pat1, however newlines or not nothing allows it to match even though it exists in the list. with wildcards or without. Commented Feb 8, 2018 at 3:40
  • To see what's REALLY in your variables, try od -c <<<"$pat2". or printf '%q\n' "$pat2". Quotes are important. Commented Feb 8, 2018 at 4:13
  • and you meant |tr -d '\n' didn't you? Good idea with the od debugging. Good luck to all. Commented Feb 8, 2018 at 4:19
  • wow yeah that is useful, thank you all for the assistance. Very helpful need to remember to mind those invisibles. Commented Feb 8, 2018 at 4:45

2 Answers 2

1

I put your pat1 and pat2 values in files and didn't need to use | anywhere.

#!/bin/bash

pat1=$(cat pat1|tr '\012' ' ')
pat2=$(<pat2)
#tst pat2="10.1"
echo "$pat1"

case "$pat1" in
  *$pat2*)
    echo 'match'
    ;;
  *)
    echo 'nomatch'
    ;;
esac

Produces

#dbg:pat2=9.5.0    pat1=9.5.0 9.5.0 9.5 9.5.0 4.8.7 6.12.3 8.9.4
match

If I un-comment the #tst pat2 line, the output is

#dbg:pat2=10.1    pat1=9.5.0 9.5.0 9.5 9.5.0 4.8.7 6.12.3 8.9.4
nomatch

Is there any chance your data was created for MS Windows? If so, check for Windows line endings with

 head -10 file | cat -vet

if you see ^M$ at the end of each line, then run dos2unix file .... (multiple file can be processed in one invocation, and the original file is overwritten with the same name.

IHTH nomatch

Sign up to request clarification or add additional context in comments.

2 Comments

oh my gosh i cant believe I didnt see this... I even got that as output at one point in a grep test : grep: 9.5.0\033[0m: No such file or directory.... cat -vet, so useful! thank you so much. printing the variables piped to cat -vet revealed the issue. thank you all pat1 = 9.5.0 9.5.0 9.59.5.0 4.8.7 6.12.3 8.9.4$ pat2 = 9.5.0^[[0m$
the \003[0m stuff looks like colorizing output. ls in many linux distributions has it turned on by default. man ls and there is something like --color=never that should eliminate that, That is ls -l --color=never files*. Good luck.
1

The grep version is almost right, but you need to quote $pat1, otherwise the newlines will be converted to spaces and everything will be on one line.

if echo "$pat1" | grep -F -q "$pat2"
then
    echo "matched"
else
    echo "nomatch"
fi

I've also added the -F option to grep so it will treat $pat2 as a fixed string rather than a regular expression.

DEMO

8 Comments

That would be fine honestly, new lines or not, I even tested by adding | tr -d '/n' on the $pat1 but it still fails. Sadly even this if test is giving nomatch as the result. unsure why. ~$ ./test.sh grep: brackets ([ ]) not balanced nomatch
I don't see any brackets in $pat2 in the question. But I suspect you need to use grep -F because you're not really matching a regular expression, you want to match fixed strings.
thank you greatly appreciate it. very helpful to know. I suspect the bracket not balanced is due to the fact that there was an ansi code for color reset on the end of my pat2 variable. so the pat2 variable actually equaled: 9.5.0^[[0m$, after i used a sed pattern filtering it out it matched using your grep method as well. thanks!
Programs that send color codes should usually disable that when stdout is not a terminal.
yeah so im pulling this info from another shell script, which is actually simply a function. if you check out the source code on github for node version manager, you will see how i get my variables. Really its a hacky way for me to get the latest version available from nvm. its not pretty but it does the job for what i need it to. and the script was definitely not intended to be used in this way.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.