Grep: अप्रत्याशित परिणाम जब मैन पेज से हेडिंग में शब्दों की खोज होती है


19

जब मैं macOS पर एक आदमी पृष्ठ को टटोलने की कोशिश कर रहा हूं तो मैं अजीब व्यवहार कर रहा हूं। उदाहरण के लिए, बैश मैन पेज में स्पष्ट रूप से स्ट्रिंग की घटना है NAME:

$ man bash | head -5 | tail -1
NAME

और अगर मैं जीआरईपी के लिए nameमैं परिणाम प्राप्त करते हैं, लेकिन अगर मैं मेरे लिए जीआरपी है NAME:

$ man bash | grep 'NAME'
$ man bash | grep NAME

मैंने अन्य बड़े शब्दों की कोशिश की है जो मुझे पता है कि वहां हैं, और पैदावार के परिणामों की SHELLखोज करते समय BASHपैदावार के लिए कुछ भी नहीं खोज रहा है।

यहाँ क्या चल रहा है?

अद्यतन : सभी उत्तर के लिए धन्यवाद! मैंने उस संदर्भ को जोड़ना उचित समझा, जिसमें मैं इसमें भाग गया था। मैं लपेटने के लिए एक बैश फ़ंक्शन लिखना चाहता था manऔर उन मामलों में जहां मैंने शेल बेसिन के लिए मैन पेज देखने की कोशिश की है, बैश मैन पेज के संबंधित अनुभाग पर जाएं। एक बेहतर तरीका हो सकता है, लेकिन यहाँ मैं वर्तमान में क्या कर रहा हूँ:

man () {
  case "$(type -t "$1")" in
    builtin)
      local pattern="^ *$1"

      if bashdoc_match "$pattern \+[-[]"; then
        command man bash | less --pattern="$pattern +[-[]"
      elif bashdoc_match "$pattern\b"; then
        command man bash | less --pattern="$pattern[[:>:]]"
      else
        command man bash
      fi
      ;;
    keyword)
      command man bash | less --hilite-search --pattern='^SHELL GRAMMAR$'
      ;;
    *)
      command man "$@"
      ;;
  esac
}

bashdoc_match() {
  command man bash | col -b | grep -l "$1" > /dev/null
}


आप कौन से ऑपरेटिंग सिस्टम का उपयोग कर रहे हैं? मुझे यकीन है कि स्वीकृत उत्तर सही है, लेकिन IO मेरे आर्क लिनक्स बॉक्स पर इसे पुन: पेश नहीं कर सका। man bash | grep NAMEउम्मीद के मुताबिक काम करता है।
terdon

@terdon मैं macOS पर हूं। मुझे यह व्यवहार बैश 3.2 और 4.4.5
ivan

एक तरफ के रूप में: यदि आप किसी बिल्डिन का पता लगाते हैं, तो आप helpइसकी जानकारी प्राप्त करने के लिए बस बैश कमांड का उपयोग कर सकते हैं।
जो

@ समस्या यह है कि मैं अक्सर helpपरिणाम बहुत अधिक बाहर जाने लगता है। उदाहरण के लिए, अनुभाग में help completeबनाम देखें । completeman bash
ivan

जवाबों:


33

यदि आप गैर-मुद्रण योग्य वर्णों को दिखाने के | sed -n lलिए उस tailआदेश में एक जोड़ते हैं , तो आपको संभवतः कुछ दिखाई देगा:

N\bNA\bAM\bME\bE

यही है, प्रत्येक चरित्र को Xबैकस्पेस के रूप में लिखा गया है X। आधुनिक टर्मिनलों पर, चरित्र खुद के ऊपर लिखा जा रहा है (जैसा कि बैकस्पेस उर्फ ​​बीएस उर्फ \bउर्फ ^Hचरित्र है जो बिना किसी अंतर के कर्सर को एक कॉलम बाईं ओर ले जाता है)। लेकिन प्राचीन टेली-टाइपराइटरों में, यह चरित्र को बोल्ड में प्रदर्शित करने का कारण बनता है क्योंकि यह दो बार स्याही के रूप में मिलता है।

फिर भी, पेजर बोल्ड को समझने के लिए उस प्रारूप को पसंद करते हैं more/ lessकरते हैं, इसलिए अभी भी roffबोल्ड टेक्स्ट का उत्पादन करना है।

कुछ पुरुष कार्यान्वयन इस तरह से कॉल करेंगे roffकि उन अनुक्रमों का उपयोग नहीं किया जाता है (या आंतरिक रूप col -b -p -xसे उन्हें पट्टी करने के लिए कॉल करें जैसे कि man-dbकार्यान्वयन के मामले में (जब तक कि MAN_KEEP_FORMATTINGपर्यावरण चर सेट नहीं किया जाता है), और आउटपुट का पता लगाने पर पेजर को आमंत्रित न करें। एक टर्मिनल पर नहीं जा रहा है (इसलिए man bash | grep NAMEवहां काम करेगा), लेकिन आपका नहीं।

आप col -bउन दृश्यों को हटाने के लिए उपयोग कर सकते हैं ( अंडरलाइन के लिए अन्य प्रकार ( _बीएस X) और साथ ही) हैं।

जीएनयू का उपयोग कर सिस्टम के लिए roff(जीएनयू या FreeBSD) की तरह, आप उन दृश्यों सुनिश्चित करते हुए पहली जगह में इस्तेमाल किया जा रहा से बचने कर सकते -c -b -uविकल्प को पास किया जाता grottyसुनिश्चित करते हुए उदाहरण के लिए, -P-cbuविकल्प के लिए पारित कर दिया है groff

उदाहरण के लिए एक आवरण लिपि बनाकर, जिसे कहा जाता है groff:

#! /bin/sh -
exec /usr/bin/groff -P-cbu "$@"

कि आपने / usr / bin / groff के आगे रखा $PATH

MacOS के साथ ' man(GNU का उपयोग करके roff), आप एक के man-no-overstrike.confसाथ बना सकते हैं :

NROFF /usr/bin/groff -mandoc -Tutf8 -P-cbu

और कॉल करें man:

man -C man-no-overstrike.conf bash | grep NAME

जीएनयू के साथ फिर भी roff, यदि आप GROFF_SGRपर्यावरण चर निर्धारित करते हैं (या GROFF_NO_SGRसंकलन समय पर कैसे चूक को निर्धारित किया गया है) के आधार पर चर सेट नहीं करते हैं , तो grotty(जब तक कि यह -cविकल्प पारित नहीं होता है) एएनएसआई एसजीआर टर्मिनल एस्केप सीक्वेंस का उपयोग करेगा चरित्र विशेषताओं के लिए उन बी एस चाल के। विकल्प के lessसाथ बुलाए जाने पर उन्हें समझें -R

FreeBSD का आदमी तब तक विकल्प के grottyसाथ कॉल करता -cहै जब तक कि आप MANCOLOR वैरिएबल सेट करके रंग नहीं पूछ रहे हैं (जिसमें एएनएसआई SGR एस्केप सीक्वेंस का उपयोग करने के लिए डिफ़ॉल्ट रूप से -cपास नहीं होता है grottyऔर grottyवापस लौटता है)।

MANCOLOR=1 man bash | grep NAME

वहां काम करेंगे।

डेबियन पर, GROFF_SGR डिफ़ॉल्ट नहीं है। यदि तुम करो:

GROFF_SGR=1 man bash | grep NAME

हालाँकि, क्योंकि manstdout एक टर्मिनल नहीं है, यह अपने आप में एक GROFF_NO_SGRचर भी पास कर लेता है grotty(मुझे लगता है कि यह col -bpxबीएस दृश्यों को स्ट्रिप करने के लिए उपयोग कर सकता है क्योंकि colयह नहीं जानता कि एसजीआर अनुक्रमों को कैसे छीनना है, हालांकि यह अभी भी है यह करता है MAN_KEEP_FORMATTING) जो हमारे ऊपर हावी है GROFF_SGR। आप इसके बजाय कर सकते हैं:

GROFF_SGR=1 MANPAGER='grep NAME' man bash

(एक टर्मिनल में) एसजीआर से बचने के क्रम के लिए।

उस समय, आप देखेंगे कि उनमें से कुछ NAME टर्मिनल पर (और एक less -Rपेजर में) बोल्ड दिखाई देते हैं । यदि आप आउटपुट sed -n l( MANPAGER='sed -n /NAME/l') को खिलाते हैं , तो आपको कुछ ऐसा दिखाई देगा:

\033[1mNAME\033[0m$

\e[1mएएनएसआई संगत टर्मिनलों में बोल्ड को सक्षम करने के लिए अनुक्रम कहां है, और \e[0mडिफ़ॉल्ट पर सभी एसजीआर विशेषताओं को वापस करने का अनुक्रम है।

उस पाठ पर grep NAMEकाम करता है जिसमें वह पाठ सम्‍मिलित है NAME, लेकिन आपको अभी भी समस्‍या हो सकती है यदि पाठ की तलाश में जहां उसके कुछ भाग बोल्‍ड / कमतर हों ...


2
वाह, बहुत दिलचस्प है वहाँ भौतिक टेली प्रकार की विरासत को देखने के लिए। दो बार जितनी स्याही => बोल्ड। परिपूर्ण अर्थ बनाता है
ivan

1
मैं sed -n lएक विकल्प के रूप में प्यार कर रहा हूँ od
टॉम हेल

13

यदि आप किसी भी मैनुअल पेज को देखते हैं, तो आप देखेंगे कि हेडर बोल्ड हैं। यह उन्हें नियंत्रण वर्णों के साथ स्वरूपण के माध्यम से प्राप्त किया जाता है। ऐसा करने में सक्षम होने के लिए grepकि आप चाहते हैं, इन्हें हटा दिया जाना चाहिए।

इसके लिए colउपयोगिता का उपयोग किया जा सकता है:

$ man bash | col -b | grep 'NAME'

-bविकल्प निम्नलिखित विवरण नहीं है OpenBSD पर :

किसी भी बैकस्पेस को आउटपुट न करें, प्रत्येक कॉलम की स्थिति के लिए लिखे गए केवल अंतिम वर्ण को प्रिंट करें। यह मैंडॉक (1) के उत्पादन को संसाधित करने में उपयोगी हो सकता है।


लिनक्स col(उबंटू पर) का अंतिम वाक्य वहां नहीं है (लेकिन यह उसी तरह से काम करता है)।

लिनक्स पर, unsetting MAN_KEEP_FORMATTINGवातावरण चर (या एक रिक्त स्ट्रिंग पर स्थापित) मदद भी कर सकते हैं और करने के लिए आप की अनुमति देगा grepके उत्पादन में गुजर बिना manके माध्यम से col -b


मुझे लगता है (जैसा कि मैंने एक आर्क और उबंटू प्रणाली पर यह परीक्षण किया है) कि लिनक्स पर यह आवश्यक नहीं है, या अब और नहीं। दोनों प्रणालियों पर, NAMEबैश मैनुअल में बस NAME, नहीं \b
terdon

@terdon मैंने पहले macOS का उल्लेख नहीं किया था, इसलिए मैंने माना कि एक गलत तरीके से कॉन्फ़िगर किया गया लिनक्स सिस्टम एक संभावना है। मैंने अब लिनक्स बिट्स को ट्रिम कर दिया है।
Kusalananda

आपने कुछ भी याद नहीं किया, मैंने ओपी से पूछा कि वे किस ओएस का उपयोग कर रहे हैं क्योंकि मैं लिनक्स पर पुन: पेश नहीं कर सकता था, उन्होंने कहा कि मैकओएस और मैंने अभी इसे जोड़ा है। और मैं आपको गलत नहीं समझा रहा था, क्योंकि मुझे पता है कि वहाँ लिनक्स वितरण वहाँ हैं जहाँ MAN_KEEP_FORMATTINGचर ठीक उसी तरह काम करता है जैसा आप कहते हैं। मैं सिर्फ यह बताना चाहता था कि ऐसा हमेशा नहीं होता है।
terdon
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.