Grep: man sayfasından başlıkta kelime ararken beklenmeyen sonuçlar


19

MacOS'ta bir man sayfasını grep etmeye çalışırken garip davranışlarla karşılaşıyorum. Örneğin, Bash man sayfası açıkça dizenin bir oluşumuna sahiptir NAME:

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

Ve eğer grep için namesonuç alırsam, ama eğer grep için alamadım NAME:

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

Orada olduğunu bildiğim diğer büyük harfleri denedim ve sonuç SHELLverirken arama yaparken hiçbir şey vermez BASH.

Burada neler oluyor?

Güncelleme : Tüm cevaplar için teşekkürler! İçinde bulunduğum bağlamı eklemeye değer olduğunu düşündüm. Sarmak için bir bash işlevi yazmak istedim manve bir kabuk yerleşik için man sayfasını aramaya çalıştığım durumlarda, Bash man sayfasının ilgili bölümüne atlayın. Daha iyi bir yol olabilir, ama şu anda sahip olduğum şey:

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
}


Hangi işletim sistemini kullanıyorsunuz? Eminim kabul edilen cevap doğrudur ancak ES bunu Arch Linux kutumda üretemedi. man bash | grep NAMEbeklendiği gibi çalışır.
terdon

@terdon macOS kullanıyorum. Bu davranışı Bash 3.2 ve 4.4.5 ile anladım
ivan

Bir kenara olduğu gibi: bir yerleşkeyi tespit ederseniz help, bilgi almak için bash komutunu kullanabilirsiniz.
Joe

@Joe Sorun şu ki, helpsonuçları çok fazla dışarıda bırakıyorum. Check out help completevs completebölüm in man bashörneğin.
ivan

Yanıtlar:


33

Eğer bir eklerseniz | sed -n lo kadar tailkomuta, muhtemelen böyle bir şey göreceksiniz olmayan yazdırılabilir karakterleri göstermek için:

N\bNA\bAM\bME\bE

Yani, her karakter XBackspace olarak yazılır X. Modern terminallerde, karakter kendi üzerine yazılır (Backspace aka BS aka \baka ^Himleci bir sütun sola hareket ettiren karakterdir) fark olmadan. Ancak eski tele-daktilolarda, bu, karakterin iki kat daha fazla mürekkep aldığı için kalın görünmesine neden olur.

Yine de, more/ lessdo gibi çağrı cihazları bu biçimi kalın anlamına gelir, bu yüzden roffkalın metin çıktısı almak için hala budur .

Bazı insan uygulamaları roff, bu sekansların kullanılmayacağı (veya uygulamada olduğu gibi ( ortam değişkeni ayarlanmadığı sürece) dahili olarak col -b -p -xbunları şeritlemeye çağıracak şekilde) çağıracak ve çıktıyı algıladıklarında bir çağrı cihazını çağırmayacaktır. bir terminale gitmiyor (bu yüzden orada çalışır), ama seninki değil.man-dbMAN_KEEP_FORMATTINGman bash | grep NAME

Bu col -bdizileri kaldırmak için kullanabilirsiniz ( alt çizgi için başka türler de vardır ( _BS X)).

GNU kullanarak sistemler için roff(GNU veya FreeBSD gibi), o diziler sağlayarak ilk etapta kullanılan önleyebilirsiniz -c -b -useçenekleri geçirilir grottysağlayarak örneğin -P-cbugeçirilir seçenekleri groff.

Örneğin, groffiçeren bir sarmalayıcı komut dosyası oluşturarak :

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

/ Usr / bin / groff'un önüne koyduğunuz $PATH.

MacOS 'ile man(ayrıca GNU kullanarak roff) aşağıdakilerle bir tane oluşturabilirsiniz man-no-overstrike.conf:

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

Ve şu şekilde arayın man:

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

Yine de GNU ile roff, GROFF_SGRortam değişkenini ayarlarsanız (veya GROFF_NO_SGRvarsayılanı derleme zamanında nasıl ayarlandığına bağlı olarak değişkeni ayarlamazsanız), o zaman grotty( -cseçeneği geçmediği sürece ) bunun yerine ANSI SGR terminal kaçış dizilerini kullanır karakter özellikleri için bu BS hileleri. seçeneği lessile çağrıldığında onları anlamak -R.

FreeBSD adam aramaları grottyile -copsiyona soran sürece renkler MANCOLOR değişkeni (bu durumda ayarlayarak -cgeçmedi grottyve grottyANSI SGR çıkış sırasını orada kullanmanın varsayılan geri döner).

MANCOLOR=1 man bash | grep NAME

orada çalışacak.

Debian'da, GROFF_SGR varsayılan değildir. Yaparsan:

GROFF_SGR=1 man bash | grep NAME

Bununla birlikte, man's stdout bir terminal olmadığı için, bir GROFF_NO_SGRdeğişkeni de geçirmesi kendi başına alır grotty(Sanırım hala olsa bile, SGR sekanslarının nasıl şeritleneceğini bilmediği col -bpxiçin BS sekanslarını colşeritlemek için kullanılabilir. bunu yapar MAN_KEEP_FORMATTING) GROFF_SGR. Bunun yerine şunları yapabilirsiniz:

GROFF_SGR=1 MANPAGER='grep NAME' man bash

(bir terminalde) SGR kaçış sekanslarına sahiptir.

O zaman, bu NAME'lerin bazılarının terminalde kalın olarak (ve bir less -Rçağrı cihazında) göründüğünü fark edeceksiniz . Çıkışı sed -n l( MANPAGER='sed -n /NAME/l') öğesine beslerseniz, şöyle bir şey görürsünüz:

\033[1mNAME\033[0m$

\e[1mANSI uyumlu terminallerde kalın yazı tipini etkinleştirme \e[0msırası ve tüm SGR niteliklerini varsayılana döndürme sırası nerede .

Bu metinde grep NAME, metnin içerdiği gibi çalışır NAME, ancak metnin yalnızca bölümlerinin kalın / altı çizili olduğu yerlerde arama yaparken sorun yaşayabilirsiniz ...


2
Vay be, orada fiziksel tele-tipin mirasını görmek oldukça ilginç. İki kat daha fazla mürekkep => kalın. Mükemmel bir anlam ifade ediyor
ivan

1
Bunun sed -n lyerine geçmeyi seviyorum od.
Tom Hale

13

Herhangi bir manuel sayfaya bakarsanız, başlıkların kalın olduğunu fark edeceksiniz. Bu, kontrol karakterleriyle biçimlendirilerek elde edilir. İstediğinizi grepbeğenebilmek için bunlar çıkarılmalıdır.

Yardımcı colprogram bunun için kullanılabilir:

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

-bSeçenek aşağıdaki açıklama vardır OpenBSD'deki :

Yalnızca her sütun konumuna yazılan son karakteri yazdırarak hiçbir arka alan çıkmayın. Bu, mandoc (1) 'in çıktısının işlenmesinde yararlı olabilir.


Linux colkılavuzunda (Ubuntu'da) son cümle yok (ama aynı şekilde çalışıyor).

Linux'ta, unsetting MAN_KEEP_FORMATTINGortam değişkeni (veya boş bir dizeye ayarlama) da yardım edebilir ve sizi sağlayacak grepçıktısını geçmeden maniçinden col -b.


Sanırım (bunu bir Arch ve Ubuntu sisteminde test ettiğim gibi) Linux'ta bunun gerekli olmadığını ya da artık gerekli olmadığını düşünüyorum. Her iki sistemde, NAMEbash kılavuzundaki sadece NAMEhayır \b.
terdon

@terdon Önce macOS'tan bahsetmedim, bu yüzden yanlış yapılandırılmış bir Linux sisteminin bir olasılık olduğunu varsaydım. Şimdi Linux bitlerini kestim.
Kusalananda

Hiçbir şeyi kaçırmadınız, OP'ye hangi işletim sistemini kullandıklarını sordum çünkü Linux'ta çoğaltma yapamadım, macOS dediler ve şimdi ekledim. Ve yanıldığını ima etmiyordum, çünkü bildiğim kadarıyla, MAN_KEEP_FORMATTINGdeğişkenin tam olarak söylediğin gibi çalıştığı Linux dağıtımları var . Sadece bunun her zaman böyle olmadığını belirtmek istedim.
terdon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.