Шукайте man-сторінки, які містять ВСІ слова "foo" 'bar' та 'baz'


12

Я б хотів шукати сторінки, на яких містяться ВСІ слова "foo", "bar" та "baz".

Якщо можливо, я хотів би проглянути весь текст (а не лише ім’я та опис) усіх чоловічих сторінок.

Я здогадуюсь щось подібне

man -K foo AND bar AND baz

чи працював мій сценарій? Ви не давали жодних відгуків :)
polym

Відповіді:


5

Я реалізував сценарій, який робить саме це.

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

Здогадайтесь, це було марною тратою часу :(

Редагувати: Начебто

man -K expr1 expr2 expr3

не працювало?

Редагувати: Тепер ви можете передати сценарії через пошукові терміни через ./script foo bar


Схоже, сценарій - це єдиний спосіб.
Graeme

2
Дивно, але ^ правда ^ - але було весело голосувати за
марну трату

Використовуючи різні аргументи так і є or, я лише думав, що це andтому, що я не перевірив його належним чином.
Graeme

3

Кілька думок щодо написання цього сценарію:

  • Використовується manpathдля отримання місця розташування сторінок "man". Якщо я додам /home/graeme/.cabal/binдо своїх PATH, manpathman) знайду чоловічі сторінки в /home/graeme/.cabal/share/man.

  • Використовуйте man man для розпакування та форматування сторінок перед пошуком, таким чином ви просто шукаєте сам текст man, а не будь-які коментарі тощо у сирому файлі. Використання manпотенційно може мати справу з декількома форматами.

  • Збереження відформатованих сторінок у темпфілі дозволить уникнути численних декомпресій і має значно прискорити роботу.

Ось іде (з bashі GNU знайти):

#!/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

Не настільки повно, як відповідь @ polym, але я збирався запропонувати щось подібне

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)

Зверніть увагу , що я додав -w(матч слів) перейти до greps- який не може бути те , що ви хочете (ви хочете включити матчі , як Foo лиш і горіховий бар ?)


Дуже ввічливо вас запитують.
mikeserv

0

Цей підхід є неперевіреним, але досить простим (дурним простим), і я вважаю, що він повинен працювати, навіть якщо він неефективний:

#!/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[@]}"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.