Tìm kiếm các trang man chứa TẤT CẢ các từ 'foo' 'bar' và 'baz'


12

Tôi muốn tìm kiếm các trang man chứa TẤT CẢ các từ 'foo', 'bar' và 'baz'.

Nếu có thể, tôi muốn tìm kiếm trong tất cả các văn bản (không chỉ tên và mô tả) của tất cả các trang man.

Tôi đoán một cái gì đó như

man -K foo AND bar AND baz

kịch bản của tôi đã làm việc? bạn đã không đưa ra bất kỳ phản hồi nào :)
polym

Câu trả lời:


5

Tôi đã thực hiện một kịch bản thực hiện chính xác điều này.

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

Đoán là lãng phí thời gian :(

Chỉnh sửa: Có vẻ như

man -K expr1 expr2 expr3

không làm việc

Chỉnh sửa: Bạn có thể chuyển các tập lệnh ngay bây giờ cụm từ tìm kiếm của bạn thông qua ./script foo bar


Dường như một kịch bản là cách duy nhất sau tất cả.
Graeme

2
Lạ nhưng ^ đúng ^ - nhưng thật vui khi bầu chọn vì lãng phí thời gian ...
mikeerv

Chỉ sử dụng các đối số khác nhau or, tôi chỉ nghĩ rằng đó là andvì tôi đã không kiểm tra nó đúng cách.
Graeme

3

Một vài suy nghĩ về kịch bản này:

  • Sử dụng manpathđể có được vị trí của các trang man. Nếu tôi thêm /home/graeme/.cabal/binvào PATH, manpath(và man) sẽ tìm thấy các trang man trong /home/graeme/.cabal/share/man.

  • Sử dụng chính man để giải nén và định dạng các trang trước khi tìm kiếm, theo cách này bạn chỉ tìm kiếm chính văn bản của người đàn ông đó chứ không phải bất kỳ bình luận nào trong tập tin thô. Sử dụng mansẽ có khả năng đối phó với nhiều định dạng.

  • Lưu các trang được định dạng trong tempfile sẽ tránh được nhiều lần giải nén và sẽ tăng tốc độ đáng kể.

Ở đây đi (với bashvà tìm 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

Không đầy đủ như câu trả lời của @ polym, nhưng tôi sẽ đề xuất một cái gì đó như

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)

Lưu ý rằng tôi đã thêm một -wchuyển đổi (khớp từ) vào greps- có thể không phải là những gì bạn muốn (bạn có muốn bao gồm các kết hợp như foo lish và nut bar không?)


Rất lịch sự của bạn để hỏi.
mikeerv

0

Cách tiếp cận này chưa được kiểm chứng nhưng khá đơn giản (ngu ngốc đơn giản) và tôi hy vọng nó sẽ hoạt động, ngay cả khi không hiệu quả:

#!/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[@]}"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.