Recherchez les pages de manuel qui contiennent TOUS les mots «foo» «bar» et «baz»


12

Je voudrais rechercher des pages de manuel qui contiennent TOUS les mots «foo», «bar» et «baz».

Si possible, je voudrais rechercher dans tout le texte (pas seulement le nom et la description) de toutes les pages de manuel.

Je devine quelque chose comme

man -K foo AND bar AND baz

mon script a-t-il fonctionné? u n'a donné aucun commentaire :)
polym

Réponses:


5

J'ai implémenté un script qui fait exactement cela.

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

Je suppose que c'était une perte de temps :(

Edit: Semble comme

man -K expr1 expr2 expr3

n'a pas fonctionné?

Edit: Vous pouvez passer les scripts maintenant vos termes de recherche via ./script foo bar


On dirait qu'un script est le seul moyen après tout.
Graeme

2
Étrange mais ^ vrai ^ - mais c'était amusant de voter pour une perte de temps ...
mikeserv

En utilisant différents arguments or, je pensais que c'était andparce que je ne l'avais pas testé correctement.
Graeme

3

Quelques réflexions sur l'écriture de ce script:

  • Utilisation manpathpour obtenir le (s) emplacement (s) des pages de manuel. Si j'ajoute /home/graeme/.cabal/binà mon PATH, manpath(et man) trouvera des pages de manuel dans /home/graeme/.cabal/share/man.

  • Utilisez man lui-même pour décompresser et formater les pages avant de rechercher, de cette façon vous recherchez simplement le texte man lui-même et non les commentaires, etc. dans le fichier brut. L'utilisation manconcernera potentiellement plusieurs formats.

  • L'enregistrement des pages formatées dans un fichier temporaire évitera les décompressions multiples et devrait accélérer considérablement les choses.

Voici (avec bashet 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

Pas aussi complet que la réponse de @ polym, mais j'allais suggérer quelque chose comme

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)

Notez que j'ai ajouté un -wcommutateur (correspondance de mots) au greps- ce qui n'est peut-être pas ce que vous voulez (voulez-vous inclure des correspondances comme foo lish et nut bar ?)


Très poli de votre part de demander.
mikeserv

0

Cette approche n'est pas testée mais assez simple (stupide simple) et je m'attends à ce qu'elle fonctionne, même si elle est inefficace:

#!/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[@]}"
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.