Suche nach Manpages, die ALLE Wörter „foo“, „bar“ und „baz“ enthalten.

Suche nach Manpages, die ALLE Wörter „foo“, „bar“ und „baz“ enthalten.

Ich möchte nach Manpages suchen, die ALLE Wörter „foo“, „bar“ und „baz“ enthalten.

Wenn möglich, möchte ich den gesamten Text (nicht nur Name und Beschreibung) aller Manpages durchsuchen.

Ich vermute so etwas wie

man -K foo AND bar AND baz

Antwort1

Ich habe ein Skript implementiert, das genau dies tut.

if [ $# -eq 0 ]; then
  PATTERNS=(NAME AUTHOR EXAMPLES FILES)
else
  PATTERNS=( "$@" )
fi

[ ${#PATTERNS[@]} -lt 1 ] && echo "Needs at least 1 pattern to search for" && exit 1

for i in $(find /usr/share/man/ -type f); do
  TMPOUT=$(zgrep -l "${PATTERNS[0]}" "$i")
  [ -z "$TMPOUT" ] && continue

  for c in `seq 1 $((${#PATTERNS[@]}-1))`; do
    TMPOUT=$(echo "$TMPOUT" | xargs zgrep -l "${PATTERNS[$c]}")
    [ -z "$TMPOUT" ] && break
  done

  if [ ! -z "$TMPOUT" ]; then
    #echo "$TMPOUT" # Prints the whole path
    MANNAME="$(basename "$TMPOUT")"
    man "${MANNAME%%.*}"
  fi
done

Ich schätze, es war Zeitverschwendung :(

Bearbeiten: Scheint so

man -K expr1 expr2 expr3

hat nicht geklappt?

Edit: Ihr könnt den Skripten nun eure Suchbegriffe übergeben über./script foo bar

Antwort2

Einige Gedanken zum Skripting:

  • Wird verwendet manpath, um den/die Speicherort(e) der Manpages abzurufen. Wenn ich /home/graeme/.cabal/binzu meinem hinzufüge PATH, werden manpath(und man) Manpages in gefunden /home/graeme/.cabal/share/man.

  • Verwenden Sie man selbst, um die Seiten vor der Suche zu dekomprimieren und zu formatieren. Auf diese Weise durchsuchen Sie nur den man-Text selbst und nicht Kommentare usw. in der Rohdatei. Die Verwendung mankann möglicherweise mehrere Formate verarbeiten.

  • Durch das Speichern der formatierten Seiten in einer temporären Datei werden mehrfache Dekomprimierungen vermieden und die Vorgänge sollten erheblich beschleunigt werden.

Hier geht's (mit bashGNU find):

#!/bin/bash

set -f; IFS=:
trap 'rm -f "$temp"' EXIT
temp=$(mktemp --tmpdir search_man.XXXXXXXXXX)

while IFS= read -rd '' file; do
  man "$file" >"$temp" 2>/dev/null

  unset fail
  for arg; do
    if ! grep -Fq -- "$arg" "$temp"; then
      fail=true
      break
    fi
  done

  if [ -z "$fail" ]; then
    file=${file##*/}
    printf '%s\n' "${file%.gz}"
  fi
done < <(find $(manpath) -type d ! -name 'man*' -prune -o -type f -print0)

Antwort3

Nicht so vollständig wie @polyms Antwort, aber ich wollte so etwas vorschlagen wie

while IFS= read -rd $'\0' f; do 
  zgrep -qwm1 'foo' "$f" && \
  zgrep -qwm1 'bar' "$f" && \
  zgrep -qwm1 'baz' "$f" && \
  printf '%s\n' "$f"
done < <(find /usr/share/man -name '*.gz' -print0)

Beachten Sie, dass ich einen -w(Wortübereinstimmung)-Schalter zu greps- hinzugefügt habe, was vielleicht nicht das ist, was Sie wollen (möchten Sie Übereinstimmungen wiefoolish und NussBar?)

Antwort4

Dieser Ansatz ist ungetestet, aber ziemlich einfach (blöd einfach), und ich gehe davon aus, dass er funktionieren sollte, auch wenn er ineffizient ist:

#!/bin/bash

if [ "$#" -eq 0 ]; then
  echo "Provide arguments to search all man pages for all arguments." >&2
  echo "Putting rare search terms first will improve performance." >&2
  exit
fi

if [ "$#" -eq 1 ]; then
  exec man -K "$@"
fi

pages=( $(man -wK "$1") )
shift
while [ "$#" -gt 1 ]; do
  pages=( $(zgrep -l "$1" "${pages[@]}") )
  shift
done
exec man "${pages[@]}"

verwandte Informationen