web-dev-qa-db-ja.com

一致するものだけでなく、すべての行を出力するようにgrepを説得する

次のファイルがあるとします。

$ cat test

test line 1
test line 2
line without the search Word
another line without it
test line 3 with two test words
test line 4

デフォルトでは、grepは検索語を含む各行を返します。

$ grep test test

test line 1
test line 2
test line 3 with two test words
test line 4

--colorパラメータをgrepに指定すると、検索式に一致する行の部分が強調表示されますが、式を含む行のみが返されます。 grepにソースファイルのすべての行を出力させ、一致する部分を強調表示する方法はありますか?

これを達成するための私の現在の恐ろしいハック(少なくとも、一致がなく、10000以上の連続する行がないファイルに対して)は次のとおりです。

$ grep -B 9999 -A 9999 test test

Screenshot of the two commands

grepがこれを達成できない場合、同じ機能を提供する別のコマンドラインツールはありますか?私は ack をいじってみましたが、それにオプションがないようです。

127
Michael Mrozek
grep --color -E "test|$" yourfile

ここで行っているのは、$パターンとテストパターン、明らかに$には色付けするものが何もないため、テストパターンのみに色が付けられます。 -Eは、拡張正規表現マッチングをオンにするだけです。

次のようにして、簡単に関数を作成できます。

highlight () { grep --color -E "$1|$" "${@:1}" ; }
194
jacksonh
ack --passthru --color string file

ubuntuとDebianの場合、ackの代わりにack-grepを使用します

ack-grep --passthru --color string file

これを行う別の方法properlyandportablywith grep(受け入れられた回答のように交互に2つの正規表現を使用する以外に)は、nullパターン(およびそれぞれnull文字列)を介します。
両方で同じように機能するはずです-Eおよび-F以降のスイッチ 標準ごと

-E
    Match using extended regular expressions. 
    [...] A null ERE shall match every line.

そして

-F
    Match using fixed strings.
    [...] A null string shall match every line.

だからそれは単に実行することの問題です

grep -E -e '' -e 'pattern' infile

とそれぞれ

grep -F -e '' -e 'string' infile
13
don_crissti

私はそのようなことに使用する次の関数を持っています:

highlight () {
    Perl -pe "s/$1/\e[1;31;43m$&\e[0m/g"
}

内部的には見た目が醜く、使いやすく使いやすいです。

cat some_file.txt | highlight some_Word

または、もう少し現実的な例として:

tail -f console.log | highlight ERROR

131および43\e[の後)を別の値に変更することで、色を好きなように変更できます(grepでは難しいかもしれません-よくわかりません)。使用する codesall over the place ですが、簡単な紹介です。1はテキストを太字にし、31は赤にします。 43は黄色の背景を提供します。 32または33は異なる色であり、44または45は異なる背景になります。傾斜している場合は、(5を使用して)点滅させることもできます。

これは特別なPerlモジュールを使用せず、Perlはほぼユビキタスなので、ほぼどこでも機能することを期待しています。 grepソリューションは非常に賢いですが、grepの--colorスイッチはどこでも利用できるわけではありません。たとえば、bashを実行しているSolarisボックスとkshを実行している別のSolarisマシン、およびzshを実行しているローカルのMac OS Xマシンでこのソリューションを試したところです。すべてうまくいきました。しかし、Solarisはgrep --colorソリューションで窒息しました。

また、ackは素晴らしいので、まだ発見していない人にはお勧めしますが、作業している多くのサーバーのいくつかにインストールするのに問題がありました。 (理由は忘れます:必要なPerlモジュールに関連していると思います。)

everできなかったPerlがインストールされている(組み込み型システム、Linksysルーターなどを除く)私は、これはほとんど普遍的に使用可能なソリューションだと思います。

11
iconoclast

Grepを使用する代わりに、Lessを使用できます。

less file

次のように検索します:/pattern Enter

この意志:

  1. 最初に一致する行までスクロール
  2. そこから始まるすべての行を出力する
  3. すべての一致を強調表示

次の一致する行にスクロールするには:n

前の一致する行にスクロールするには:N

ハイライトを切り替えるには: Esc u

また、必要に応じて ハイライト色 を変更できます。

3
Steven Penny

あなたが試すことができます:

Perl -MTERM::ANSIColor -nle '/pattern/ ? print colored($_, 'color') : print' test

ただし、あまり移植性がなく、Perlがインストールされている場合でも、別のモジュールをダウンロードする必要がある場合があります。さらに、検索ワードだけでなく、行全体に色を付けます。

2
gvkv

これまでの回答では、portableソリューションは提供されていません。

これはポータブルです1 シェル関数I すでに投稿されています 非標準のツールやPerlackggrepgsedbashなどですが、POSIXシェルとPOSIX必須ユーティリティsedprintfのみが必要です。

grepc()
{
  pattern=$1
  shift
  esc=$(printf "\033")
  sed 's"'"$pattern"'"'$esc'[32m&'$esc'[0m"g' "$@"
}

あなたはそれをそのように使うことができます:

grepc string_to_search [file ...]

ハイライトの色は、sedコマンド引数でこれらのコードのいずれかを使用して調整できます(ここでは32mが緑です)。

30m black
31m red
33m yellow
34m blue
35m Magenta
36m cyan
37m white
7m reverse video

1 端末がANSIカラーエスケープシーケンスをサポートしている限り。

2
jlliagre

ripgrep

ripgrepとその--passthruパラメータを使用します。

rg --passthru pattern file.txt

Rust's regex engine の上に構築されているため、これは 最速のgreppingツール の1つです。

--passthru-一致する行と一致しない行の両方を出力します。

同様の効果を達成する別の方法は、空の文字列に一致するようにパターンを変更することです。たとえば、rg fooを使用して検索している場合、代わりにrg "^|foo"を使用すると、検索されたすべてのファイルのすべての行が出力されますが、fooの出現のみが強調表示されます。このフラグは、パターンを変更することなく同じ動作を可能にします。

2
kenorb

GNU grepの場合、これを行うにははるかに簡単な方法がありますが、移植性があるとは思えません(つまり、BSD grep):

パイプ内:

cat <file> | grep --color=always -z <query>

ファイルについて:

grep --color=always -z <query> <file>

クレジットは Cyrusの回答はこちら に送られます。

1
Erik Nomitch

sedバージョンは、bashashの両方で機能します。

#highlight
hsed(){
    local pattern="$1"
    shift
    local r=`echo -e '\e'[31m`
    local c=`echo -e '\e'[0m`
    sed "s:${pattern//:/\:}:$r\0$c:g" "$@"
}
0
yurenchen

OPがgrepを要求し、それがI RECOMMEND;です。しかし、sedの問題を懸命に解決した後、記録のために、これを使用した簡単な解決策を次に示します。

sed $'s/main/\E[31m&\E[0m/g' testt.c

または

cat testt.c | sed $'s/main/\E[31m&\E[0m/g'

mainを赤でペイントします。

  • \E[31m:赤色の開始シーケンス
  • \E[0m:完成したカラーマーク
  • &:一致したパターン
  • /g:行の最初の単語だけでなく、すべての単語
  • $'string'は、エスケープ文字が解釈されたbash文字列です

grepに関しては、^(行末)ではなく$(行頭)を使用しても機能します。例:

egrep "^|main" testt.c

そして、このクレイジーなエイリアスがI NOT RECOMMENDであることを示すために、オープンクォートを使用することもできます。

alias h='egrep -e"^|'
h main" testt.c
cat testt.c | h main"

すべての仕事! :)引用符を閉じるのを忘れても心配しないでください。bashは「継続行文字」であなたを記憶します。

0
Dr Beco