Pesquisa por man pages que contenham TODAS as palavras 'foo' 'bar' e 'baz'

12

Gostaria de pesquisar por man pages que contenham TODAS as palavras 'foo', 'bar' e 'baz'.

Se possível, gostaria de pesquisar em todo o texto (não apenas o nome e a descrição) de todas as páginas do manual.

Eu estou supondo algo como

man -K foo AND bar AND baz
    
por Tomsai 15.06.2014 / 16:45

4 respostas

5

Eu implementei um script que faz exatamente isso.

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

Acho que foi uma perda de tempo: (

Editar: parece que

man -K expr1 expr2 expr3

não funcionou?

Editar: você pode passar os scripts agora com os termos de pesquisa por meio de ./script foo bar

    
por 15.06.2014 / 17:11
3

Algumas reflexões sobre o script:

  • Usando manpath para obter a (s) localização (ões) das páginas man. Se eu adicionar /home/graeme/.cabal/bin ao meu PATH , manpath (e man ) encontrará man pages em /home/graeme/.cabal/share/man .

  • Use o próprio man para descompactar e formatar as páginas antes de pesquisar, desta forma você está apenas pesquisando o próprio texto man e não quaisquer comentários, etc. no arquivo raw. A utilização de man irá potencialmente lidar com vários formatos.

  • Salvar as páginas formatadas em um arquivo temporário evitará várias descompressões e deverá acelerar as coisas significativamente.

Aqui vai (com bash e 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)
    
por 15.06.2014 / 20:44
2

Não tão completo quanto a resposta de @polym, mas eu sugeriria algo como

while IFS= read -rd $'
while IFS= read -rd $'%pre%' 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)
' 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)

Observe que eu adicionei uma opção -w (correspondência de palavras) ao greps - que pode não ser o que você deseja (você deseja incluir correspondências como foo lish e nut bar ?)

    
por 15.06.2014 / 19:28
0

Essa abordagem não foi testada, mas é bastante simples (simples e estúpida) e espero que funcione, mesmo que seja ineficiente:

#!/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[@]}"
    
por 16.03.2018 / 01:38

Tags