Suche nach Manpages, die ALLE Wörter 'foo' 'bar' und 'baz' enthalten


12

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

hat mein script funktioniert
Du

Antworten:


5

Ich habe ein Skript implementiert, das genau das 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 :(

Edit: Scheint so

man -K expr1 expr2 expr3

hat nicht funktioniert?

Bearbeiten: Über die Skripte können Sie nun Ihre Suchbegriffe übergeben ./script foo bar


Sieht aus wie ein Skript ist der einzige Weg, schließlich.
Graeme

2
Seltsam, aber ... wahr ... - aber es hat Spaß gemacht, für Zeitverschwendung zu stimmen ...
mikeserv

Wenn orich einfach andere Argumente verwende , denke ich nur, andweil ich es nicht richtig getestet habe.
Graeme

3

Ein paar Gedanken zum Skripting:

  • Verwenden Sie manpath, um die Position (en) der Manpages abzurufen. Wenn ich /home/graeme/.cabal/binzu meinen hinzufüge PATH, werden manpath(und man) Manpages in finden /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 keine Kommentare usw. in der Rohdatei. Die Verwendung manwird möglicherweise mit mehreren Formaten umgehen.

  • Das Speichern der formatierten Seiten in einem tempfile vermeidet mehrfache Dekomprimierungen und sollte die Dinge erheblich beschleunigen.

Hier gehts (mit bashund GNU 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)

2

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

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 -wSchalter greps( Wortübereinstimmung ) zum Schalter - hinzugefügt habe, der möglicherweise nicht Ihren Wünschen entspricht (möchten Sie Übereinstimmungen wie foo lish und nut bar einfügen ?)


Sehr höflich von dir zu fragen.
mikeserv

0

Dieser Ansatz ist ungetestet, aber ziemlich einfach (dumm 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[@]}"
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.