1

A section of grep --help is:

  -E, --extended-regexp     PATTERNS are extended regular expressions
  -F, --fixed-strings       PATTERNS are strings

There are plenty examples online for the -E but I can't find any for -F

I'm not very good with regex and avoid it if I possibly can so this -F looks like a better option.

What is the syntax to grep something and see if it contains 3 different strings?

4
  • Should contain at least one of the 3 different strings or all of the 3? Jul 1 at 16:45
  • Should contain 'at least one'
    – cardamom
    Jul 1 at 16:47
  • Note that grep -F can be invoked as fgrep Jul 2 at 2:45
  • 2
    @RomanOdaisky fgrep is deprecated in favor of grep -F.
    – Ed Morton
    Jul 2 at 3:42

2 Answers 2

11

The -F option or --fixed-string, as you noted, disable the regexp engine and search for literal strings. It is useful to look for strings that are valid regular expressions, but would have a different meaning as such. E.g.:

grep -Fe '[warn]' app.log

The [warn] pattern is a valid Basic Regular Expression (BRE) and so without the -F option grep will search and catch any line with at least one of w,a, r, or n. (Note that the brackets are special in the shell too, so we need to quote them on the command line.)

As an example, assume we want to find the error messages from a log file like the following with lines like this (so, the lines with the [err] tag):

[info] terrace lights on
[err] garage door control not responding

Using grep 'err' would match both lines, as there's a hit in the word "terrace". grep '[err]' would also match both lines, as both have an "e" (and an "r"). But here, grep -F '[err]' would be a simple way to limit the match to the tags only. (Alternatively, one could use the default regex match and escape the brackets: grep -e '\[err\]', or grep -e '[[]err[]]' or even grep '[[]err]'. But that's uglier.)

If you have more patterns to search for, you can use the -e option multiple times:

grep -F -e '[warn]' -e '[debug]' -e '[err]' app.log

Lines matching any of the patterns (at least one) will be matched.

The -x, --line-regex option can also be useful in this context as it means it only considers a line a match if the whole line matches the pattern. E.g. grep -x foo will match if a line is foo but not if the line is foobar. And -Fx together would only find exactly matching lines, whatever special characters they contain.

5
  • What's going on with the square brackets? It looks like it may work without them..
    – cardamom
    Jul 1 at 17:37
  • Incidentally, grep -F is also available as fgrep. I use it all the time! Jul 2 at 9:32
  • @cardamom, the brackets are there to match brackets in the input data. See the edit, I added another example here.
    – ilkkachu
    Jul 2 at 9:48
  • 1
    @reinierpost, though fgrep (and egrep) are deprecated, and not in the POSIX spec (at least not any more, I don't know if they were before or when). Though I'd expect you're still likely to find them in most systems, as they shouldn't be too hard to implement. (A shell script with grep -F "$@" should do if you don't care too much about the corner cases like fgrep -E... Incidentally, GNU grep errors on that, and Busybox seems to give precedence to -F.)
    – ilkkachu
    Jul 2 at 9:53
  • @cardamom, also yes, spaces work as regular characters (just need to quote for the shell, but you should quote most patterns anyway). You can use grep -F '1 * 2' to look for lines with exactly the five characters 1, space, asterisk, space, 2. (as a regex It would look for a 1, at least one space, and a 2, no asterisks)
    – ilkkachu
    Jul 2 at 9:54
5

To get the lines in test.txt that have at least one of the strings hello or goodbye, you'd use:

grep -F -e hello -e goodbye test.txt

That is, the patterns to look for are given as arguments to the -e options, and the -F option tells to treat them as fixed strings. Well, that doesn't matter with the above, but e.g. a pattern like a.*b would look for a, a dot, an asterisk, and a b, instead of the regex interpretation which would be a and b with anything in between.

Alternatively, you could put the looked-for strings in a file, one per line, and use the -f option to give the filename:

$ grep -F -f patterns.txt  test.txt
you say hello when you arrive
goodbye when you leave
but rarely say hello and goodbye at the same time

(Note that it'd be much harder to do the "all given strings" test. It's rather awkward even with regexes.)

4
  • Thanks, I see.. small f is --file=FILE and big F is --fixed-strings I might end up using that small f as well but for the moment just to understand it, 'proof of concept', will stick to the first part of your example with big F
    – cardamom
    Jul 1 at 17:02
  • It looks like the -F is only used in conjunction with the -e (small e), you can't use -F without it
    – cardamom
    Jul 1 at 17:07
  • Putting back a comment someone made then deleted, if it is a string with spaces rather than just a word, it can go in these grep commands in single quotes
    – cardamom
    Jul 1 at 17:30
  • 1
    @cardamom of course you can: this answer contains one example, and here's another: grep -F '[error]' file.log. In fact, I am not sure if I have ever used -e myself, I usually go for different approaches, but I've used -F hundreds of times.
    – terdon
    Jul 1 at 17:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.