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
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
Câu trả lời:
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
or
, tôi chỉ nghĩ rằng đó là and
vì tôi đã không kiểm tra nó đúng cách.
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/bin
và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 man
sẽ 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 bash
và 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)
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 -w
chuyể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?)
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[@]}"