ค้นหาหน้าคนที่มีคำว่า '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


ดูเหมือนว่าสคริปต์เป็นวิธีเดียวหลังจากทั้งหมด
แกรม

2
แปลก แต่ ^ จริง ^ - แต่มันสนุกที่จะลงคะแนนให้เสียเวลา ...
mikeserv

ใช้ข้อโต้แย้งที่แตกต่างกันเพียงแค่orฉันคิดว่าเป็นandเพราะฉันไม่ได้ทดสอบอย่างถูกต้อง
แกรม

3

ความคิดเล็ก ๆ น้อย ๆ เกี่ยวกับการเขียนสคริปต์นี้:

  • ใช้manpathเพื่อรับตำแหน่งของ man pages ถ้าฉันจะเพิ่ม/home/graeme/.cabal/binของฉันPATH, manpath(และman) /home/graeme/.cabal/share/manจะพบหน้าคนใน

  • ใช้ man ตัวเองเพื่อขยายและจัดรูปแบบหน้าก่อนค้นหาด้วยวิธีนี้คุณเพียงแค่ค้นหาข้อความตัวเองและไม่แสดงความคิดเห็นใด ๆ ในไฟล์ raw การใช้manอาจจะเกี่ยวข้องกับหลายรูปแบบ

  • การบันทึกเพจที่จัดรูปแบบใน tempfile จะหลีกเลี่ยงการแตกไฟล์หลายไฟล์และควรเร่งให้มีความเร็วมากขึ้น

ไปที่นี่ (พร้อม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 lish และ nut barหรือไม่)


สุภาพมากที่คุณถาม
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[@]}"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.