How to Grep Exact Literal String (No Regex)

How to grep exact literal string (no regex)

Use fgrep, it's the same as grep -F (matches a fixed string).

Grepping for exact string while ignoring regex for dot character

fgrep is the same as grep -F. grep also has the -x option which matches against whole lines only. You can combine these to get what you want:

grep -Fx account.test file.txt

grep match exact substring ignoring regex syntax

Use grep -F or fgrep.

$ echo "1034" | grep -F $version # shouldn't match
$ echo "10.4" | grep -F $version
10.4

See man page:

   -F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated
by newlines, any of which is to be matched.

I was looking for the term "literal match" or "fixed string".

(See also Using grep with a complex string and How can grep interpret literally a string that contains an asterisk and is fed to grep through a variable?)

Grep exact string not working when piped

If you have pgrep, using pgrep -x mysqld would be better choice than ps + grep

From man pgrep

   pgrep, pkill - look up or signal processes based on name and other attributes

-x, --exact
Only match processes whose names (or command line if -f is specified) exactly match the pattern.

-l, --list-name
List the process name as well as the process ID. (pgrep only.)

-c, --count
Suppress normal output; instead print a count of matching processes. When count does not match any‐
thing, e.g. returns zero, the command will return non-zero value.

-n, --newest
Select only the newest (most recently started) of the matching processes.

Grep for literal strings

You can use grep for that, with the -F option.

-F, --fixed-strings       PATTERN is a set of newline-separated fixed strings

Problem with using grep to match the whole word

Update: Using fgrep -x '/user/hemanth.a' is probably a better solution here, as it avoids having to escape characters such as $ to prevent grep from interpreting them as meta-characters. fgrep performs a literal string match as opposed to a regular expression match, and the -x option tells it to only match whole lines.

Example:

> cat testfile.txt
foo
foobar
barfoo
barfoobaz

> fgrep foo testfile.txt
foo
foobar
barfoo
barfoobaz

> fgrep -x foo testfile.txt
foo

Original answer:

Try adding the $ regex metacharacter to the end of your grep expression, as in:

echo $snapshottableDirs | tr -s ' ' '\n' | grep -w '/user/hemanth.a$'. 

The $ metacharacter matches the end of the line.

While you're at it, you might also want to use the ^ metacharacter, which matches the beginning of the line, so that grep '/user/hemanth.a$' doesn't accidentally also match something like /user/foo/user/hemanth.a.

So you'd have this:

echo $snapshottableDirs | tr -s ' ' '\n' | grep '^/user/hemanth\.a$'. 

Edit: You probably don't actually want the -w here, so I've removed that from my answer.

Edit 2: @U. Windl brings up a good point. The . character in a regular expression is a metacharacter that matches any character, so grep /user/hemanth.a might end up matching things you're not expecting, such as /user/hemanthxa, etc. Or perhaps more likely, it would also match the line /user/hemanth/a. To fix that, you need to escape the . character. I've updated the grep line above to reflect this.

Update: In response to your question in the comments about how to escape a string so that it can be used in a grep regular expression...

Yes, you can escape a string so that it should be able to be used in a regular expression. I'll explain how to do so, but first I should say that attempting to escape strings for use in a regex can become very complicated with lots of weird edge cases. For example, an escaped string that works with grep won't necessarily work with sed, awk, perl, bash's =~ operator, or even grep -e.

On top of that, if you change from single quotes to double quotes, you might then have to add another level of escaping so that bash will expand your string properly.

For example, if you wanted to search for the literal string 'foo [bar]* baz$'using grep, you'd have to escape the [, *, and $ characters, resulting in the regular expression:

'foo \[bar]\* baz\$'

But if for some reason you decided to pass that expression to grep as a double-quoted string, you would then have to escape the escapes. Otherwise, bash would interpret some of them as escapes. You can see this if you do:

echo "foo \[bar]\* baz\$"
foo \[bar]\* baz$

You can see that bash interpreted \$ as an escape sequence representing the character $, and thus swallowed the \ character. This is because normally, in double quoted strings $ is a special character that begins a parameter expansion. But it left \[ and \* alone because [ and * aren't special inside a double-quoted string, so it interpreted the backslashes as literal \ characters. To get this expression to work as an argument to grep in a double-quoted string, then, you would have to escape the last backslash:

# This command prints nothing, because bash expands `\$` to just `$`,
# which grep then interprets as an end-of-line anchor.
> echo 'foo [bar]* baz$' | grep "foo \[bar]\* baz\$"

# Escaping the last backslash causes bash to expand `\\$` to `\$`,
# which grep then interprets as matching a literal $ character
> echo 'foo [bar]* baz$' | grep "foo \[bar]\* baz\\$"
foo [bar]* baz$

But note that "foo \[bar]\* baz \\$" will not work with sed, because sed uses a different regex syntax in which escaping a [ causes it to become a meta-character, whereas in grep you have to escape it to prevent it from being interpreted as a meta-character.

So again, yes, you can escape a literal string for use as a grep regular expression. But if you need to match literal strings containing characters that will need to be escaped, it turns out there's a better way: fgrep.

The fgrep command is really just shorthand for grep -F, where the -F tells grep to match "fixed strings" instead of regular expression. For example:

> echo '[(*\^]$' | fgrep '[(*\^]$'
[(*\^]$

This works because fgrep doesn't know or care about regular expressions. It's just looking for the exact literal string '[(*\^]$'. However, this sort of puts you back at square one, because fgrep will match on substrings:

> echo '/users/hemanth/dummy' | fgrep '/users/hemanth'
/users/hemanth/dummy

Thankfully, there's a way around this, which it turns out was probably a better approach than my initial answer, considering your specific needs. The -x option to fgrep tells it to only match the entire line. Note that -x is not specific to fgrep (since fgrep is really just grep -F anyway). For example:

> echo '/users/hemanth/dummy' | fgrep -x '/users/hemanth' # prints nothing

This is equivalent to what you would have gotten by escaping the grep regex, and is almost certainly a better answer than my previous answer of enclosing your regex in ^ and $.

Now, as promised, just in case you want to go this route, here's how you would escape a fixed string to use as a grep regex:

# Suppose we want to match the literal string '^foo.\ [bar]* baz$'
# It contains lots of stuff that grep would normally interpret as
# regular expression meta-characters. We need to escape those characters
# so grep will interpret them as literals.
> str='^foo.\ [bar]* baz$'
> echo "$str"
^foo.\ [bar]* baz$

> regex=$(sed -E 's,[.*^$\\[],\\&' <<< "$str")
> echo "$regex"
\^foo\.\\ \[bar]\* baz\$

> echo "$str" | grep "$regex"
^foo.\ [bar]* baz$
# Success

Again, for the reasons cited above, I don't recommend this approach, especially not when fgrep -x exists.

Is there an easy way to pass a raw string to grep?

If you are attempting to get grep to use Extended Regular Expression syntax, the way to do that is to use grep -E (aka egrep). You should also know about grep -F (aka fgrep) and, in newer versions of GNU Coreutils, grep -P.

Background: The original grep had a fairly small set of regex operators; it was Ken Thompson's original regular expression implementation. A new version with an extended repertoire was developed later, and for compatibility reasons, got a different name. With GNU grep, there is only one binary, which understands the traditional, basic RE syntax if invoked as grep, and ERE if invoked as egrep. Some constructs from egrep are available in grep by using a backslash escape to introduce special meaning.

Subsequently, the Perl programming language has extended the formalism even further; this regex dialect seems to be what most newcomers erroneously expect grep, too, to support. With grep -P, it does; but this is not yet widely supported on all platforms.

So, in grep, the following characters have a special meaning: ^$[]*.\

In egrep, the following characters also have a special meaning: ()|+?{}. (The braces for repetition were not in the original egrep.) The grouping parentheses also enable backreferences with \1, \2, etc.

In many versions of grep, you can get the egrep behavior by putting a backslash before the egrep specials. There are also special sequences like \<\>.

In Perl, a huge number of additional escapes like \w \s \d were introduced. In Perl 5, the regex facility was substantially extended, with non-greedy matching *? +? etc, non-grouping parentheses (?:...), lookaheads, lookbehinds, etc.

... Having said that, if you really do want to convert egrep regular expressions to grep regular expressions without invoking any external process, try ${regex/pattern/substitution} for each of the egrep special characters; but recognize that this does not handle character classes, negated character classes, or backslash escapes correctly.

ag: search exact string, not a pattern

The option you're looking for is

-Q --literal: Do not parse PATTERN as a regular expression. Try to match it literally.

@ https://github.com/ggreer/the_silver_searcher/blob/master/doc/ag.1.md:

grep not consider dot in exact search

You can use a regex:

cat tlds.csv | grep -E ',com\.csv$'

In this way, you tell grep that you want only those lines that have a , before com.csv, and nothing more after com.csv.

You can also use

cat tlds.csv | grep -E '[^.]com\.csv$'

to tell grep that before com.csv it's okay any char except for ..
Anyway, if I can add a suggestion I wouldn't use cat. grep can take your file as an argument, int this way:

grep -E '[^.]com\.csv$' tlds.csv

Here you can see why you should prefer not using cat.

grep matches exact string or with wildcard

grep uses regex for pattern matching. grep -w 'name1*' would make it match zero or more 1s, so name1 and name11 would match.

If it only matches name1 for you it's because you have a file named name1 in the directory and the unquoted name1* will be interpreted by the shell (globbing). Always use quotes around your arguments that contain special characters. If you use a variable, always put " around it.

To make it match any name starting with name1, make it

grep -w 'name1.*' filename
  • . means "any character"
  • .* means "any character, zero or more times".

If the input comes from some external source where * is used as a wildcard, you need to change that string before calling grep.

Example:

search_str='name1*'
new_search_str="$(sed 's/\*/.*/g' <<< "$search_str")"
grep -w "$new_search_str" filename


Related Topics



Leave a reply



Submit