Is there a way to look for a flag in a man page?

rici's helpful answer explains the problem with the original approach well.

However, there's another thing worth mentioning:

man's output contains formatting control characters, which interfere with text searches.

If you pipe to col -b before searching, these control characters are removed - note the side effect that the search results will be plain-text too.

However, grep is not the right tool for this job; I suggest using awk as follows to obtain the description of -O:

man gcc | col -b | awk -v RS= '/^\s+-O\n/'
  • RS= (an empty input-record separator) is an awk idiom that breaks the input into blocks of non-empty lines, so matching the option at the start of such a block ensures that all lines comprising the description of the option are returned.

If you have a POSIX-features-only awk such as BSD/OSX awk, use this version:

man gcc | col -b | awk -v RS= '/^[[:blank:]]+-O\n/'

Obviously, such a command is somewhat cumbersome to type, so find generic bash function manopt below, which returns the description of the specified option for the specified command from its man page. (There can be false positives and negatives, but overall it works pretty well.)

Examples:

manopt gcc O          # search `man gcc` for description of `-O`
manopt grep regexp    # search `man grep` for description of `--regexp`
manopt find '-exec.*' # search `man find` for all actions _starting with_ '-exec'

bash function manopt() - place in ~/.bashrc, for instance:

# SYNOPSIS
#   manopt command opt
#
# DESCRIPTION
#   Returns the portion of COMMAND's man page describing option OPT.
#   Note: Result is plain text - formatting is lost.
#
#   OPT may be a short option (e.g., -F) or long option (e.g., --fixed-strings);
#   specifying the preceding '-' or '--' is OPTIONAL - UNLESS with long option
#   names preceded only by *1* '-', such as the actions for the `find` command.
#
#   Matching is exact by default; to turn on prefix matching for long options,
#   quote the prefix and append '.*', e.g.: `manopt find '-exec.*'` finds
#   both '-exec' and 'execdir'.
#
# EXAMPLES
#   manopt ls l           # same as: manopt ls -l
#   manopt sort reverse   # same as: manopt sort --reverse
#   manopt find -print    # MUST prefix with '-' here.
#   manopt find '-exec.*' # find options *starting* with '-exec'
manopt() {
  local cmd=$1 opt=$2
  [[ $opt == -* ]] || { (( ${#opt} == 1 )) && opt="-$opt" || opt="--$opt"; }
  man "$cmd" | col -b | awk -v opt="$opt" -v RS= '$0 ~ "(^|,)[[:blank:]]+" opt "([[:punct:][:space:]]|$)"'
}

fish implementation of manopt():

Contributed by Ivan Aracki.

function manopt 
  set -l cmd $argv[1]
  set -l opt $argv[2] 
  if not echo $opt | grep '^-' >/dev/null
    if [ (string length $opt) = 1 ] 
      set opt "-$opt"
    else
      set opt "--$opt"
    end
  end
  man "$cmd" | col -b | awk -v opt="$opt" -v RS= '$0 ~ "(^|,)[[:blank:]]+" opt "([[:punct:][:space:]]|$)"'
end

I suspect you didn't actually use grep $'-O\n', but rather some flag recognized by grep.

From grep's point of view, you are simply passing an argument, and that argument starts with a - so it's going to be interpreted as an option. You need to do something like grep -- -O$ to explicitly flag the end of the list of options, or grep -e -O$ to explicitly flag the pattern as a pattern. In any event, you cannot include a newline in a pattern because grep patterns are actually lists of patterns separated by newline characters, so the argument $'foo\n' is actually two patterns, foo and the empty string, and the empty string will match every line.

Perhaps you searched for the flag -e since that takes a pattern as an argument, and giving it a newline as an argument will cause grep to find every line in the whole file.

For most GNU programs, such as gcc, you might find the info interface easier to navigate in, since it includes reference links, tables of contents, and even indices. The info gcc document includes an index of options, which is very useful. In some linux distributions, and somewhat surprisingly since they call themselves GNU/linux distributions, it's necessary to separately install info packages although man files are distributed with the base software. The debian/ubuntu package containing the gcc info files is called gcc-doc, for example. (The use of the -doc suffix to the package name is quite common.)

In the case of gcc you can rapidly find an option using a command like:

info gcc "option index" O

or

info gcc --index-search=funroll-loops

For programs with fewer options, it's usually good enough to use info's -O option:

info -O gawk