Cerca le pagine man che contengono TUTTE le parole 'foo' 'bar' e 'baz'


12

Mi piacerebbe cercare le pagine man che contengono TUTTE le parole "foo", "bar" e "baz".

Se possibile, mi piacerebbe cercare in tutto il testo (non solo nome e descrizione) di tutte le pagine man.

Sto indovinando qualcosa del genere

man -K foo AND bar AND baz

la mia sceneggiatura ha funzionato? non hai dato alcun feedback :)
polym

Risposte:


5

Ho implementato una sceneggiatura che fa esattamente questo.

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

Immagino sia stata una perdita di tempo :(

Modifica: sembra

man -K expr1 expr2 expr3

non ha funzionato?

Modifica: ora puoi passare gli script tramite i tuoi termini di ricerca ./script foo bar


Sembra che una sceneggiatura sia l'unico modo dopo tutto.
Graeme,

2
Strano ma ^ vero ^ - ma è stato divertente votare per perdere tempo ...
mikeserv

Usando diversi argomenti or, ho solo pensato che fosse andperché non l'ho testato correttamente.
Graeme,

3

Alcuni pensieri su come scrivere questo:

  • Usando manpathper ottenere la posizione (s) delle pagine man. Se aggiungo /home/graeme/.cabal/binal mio PATH, manpath(e man) troveranno pagine man in /home/graeme/.cabal/share/man.

  • Usa man stesso per decomprimere e formattare le pagine prima di cercare, in questo modo stai solo cercando il testo man stesso e non eventuali commenti ecc. Nel file raw. L'utilizzo manpotenzialmente tratterà con più formati.

  • Salvare le pagine formattate in un file temporaneo eviterà più decompressioni e dovrebbe accelerare notevolmente le cose.

Ecco qui (con bashe 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

Non completo come la risposta di @ polym, ma stavo per suggerire qualcosa di simile

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)

Nota che ho aggiunto un -winterruttore (corrispondenza parola) a greps- che potrebbe non essere quello che vuoi (vuoi includere corrispondenze come foo lish e barra di noci ?)


Molto educato da chiedere.
Mikeserv,

0

Questo approccio non è testato ma abbastanza semplice (stupido semplice) e mi aspetto che dovrebbe funzionare, anche se inefficiente:

#!/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[@]}"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.