2
echo "abc-vcu def" | grep -w "abc.vcu" 
echo $?

The output of the above line is 0. But abc-vcu != abc.vcu and def != abc.vcu. So it should return 1.

Command is returning true because it is assuming . and - are same. How to do exact comparing?

2
  • 2
    Why not use Bash's [[? Commented Mar 25, 2014 at 10:16
  • 1
    if you use it in script, you may want to add the -q option to grep. Commented Mar 25, 2014 at 10:26

4 Answers 4

2

What you are attempting is better achieved with a simple string comparison.

if [[ "abc-vcu def" == *"abc.vcu"* ]]; then
    echo "String B contained in String A"
else
    echo "No containment"
fi

Notice also how this avoids the antipattern of examining $?. Just to elaborate, anything that looks like

command
if [ $? == 0 ]; then ...

is better written as

if command; then ...

Tangentially, if you really do want or have to use grep, there are some options you need to understand. grep matches regular expressions, not just strings. There is a separate option to change the search expression into a string, namely -F (traditionally available as a separate command fgrep):

echo moo | grep m.o     # true
echo moo | grep -F m.o  # false

Just for completeness, note also that grep looks for a match anywhere in the input. So echo moo | grep o is true. If you really want to look for an exact match, you need the -x option (or change the expression you are grepping for):

echo moo | grep -x moo
echo moo | grep '^moo$'

Like @Kent remarks, grep will print any matching lines by default, which you probably don't want here -- you are only running grep to see if there is a match. So you need the -q flag as well. To summarize,

echo "abc-vcu def" | grep -Fxwq "abc.vcu"

Finally, you should probably also be aware of case:

case "abc-vcu def" in *"abc.vcu"*) echo true;; *) echo false;; esac

Unlike the [[ Bash-only test, case is portable all the way back to the original Bourne shell.

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

Comments

2

In grep . means any character (regular expression syntax)

If you need to match . try \.

echo "abc-vcu def" | grep -w "abc\.vcu"
echo $?

5 Comments

that works but what if we have two variables : x and y. x can contain more than 1 string and y contains a single string. x and y are random inputs by user. This wont work in that case.
Would you please not undo the edits that escape \.?
@LutzHorn: Sorry, that was not on purpose. It seems we were editing at the same time.
x can be "abc.fs def" and y can be "abc-fs". x and y are input given by users. and command is echo "$x" | grep -w "$y". echo $?. now this will again return 0. and we cant include "/" in string y as it is user input.
echo "abc-vcu def" | grep -w "^abc\.vcu$" echo $?
1

If you do want to use grep in this case, use it as follows:

echo "abc-vcu def" | grep -F -w "abc.vcu"

man grep says that with -F grep must

Interpret PATTERN as a list of fixed strings

This fixes the problem that . is recognized as 'any symbol' pattern.

1 Comment

omm... a bit strange. -F is specified by POSIX. Looks like you need to screen . by \.. echo "$x" | grep -w "${y//./\\.}"
1

Instead of using grep you could let bash do the work, especially if you intend to use variables anyway:

string1='abc-vcu def'
string2='abc.vcu'
[[ ! ${string1/*${string2}*/} ]]
echo $?

[[ expression ]] returns 0 or 1 depending on the evaluation of expression.

! is a logical not.

${parameter/pattern/string} replaces the first occurence of pattern in parameter by string, where pattern is expanded just as in pathname expansions. For the above case that means that if $string2 appears anywhere in $string1, $string1 is completely replaced by '' (an empty string), which is a logical false.

Comments

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.