各grepコマンドを実行して、結果を異なる色で強調表示しようとしています。次のような行で手動で行うことができます。
ls -l GREP_COLORS='mt=01;32' grep c | GREP_COLORS='mt=01;31' grep o | GREP_COLORS='mt=01;34' grep n | GREP_COLORS='mt=01;36' grep f
すべてのc
文字は緑色で強調表示され、すべてのo
文字は赤色で強調表示されます、など...
この例が機能するためには、grepコマンドに常に
--color=always
があることを確認する必要があります。これを.bashrc
に設定したので、grepは常に色を持ちます:
export GREP_OPTIONS='--color=always'
私が達成しようとしているのは、この機能をエイリアスでラップすることです。そのため、grep
を呼び出して、毎回異なるGREP_COLORS
値を持つことができます。新しいパイプで接続されたgrepごとに複数のシェルの考慮事項を理解し、すでに使用されていることを示すためにいくつかのファイル(色ごとに1つ)を作成することでこれを克服しようとしています。
私はいくつかの試みをしましたが、奇妙なことに、これは「最高」で動作するようです。これは.bashrc
にあります:
alias mg="mygrep"
mygrep(){
# define possible colors
COLORS=("01;32" "01;31" "01;34" "01;36")
COUNTER=0
NUM=0
# as long as the color has already been used, keep searching
while [ -f /home/lior/Desktop/mygrep_$NUM ]; do
# get a random index
let NUM=`shuf --input-range=0-$(( ${#COLORS[*]} - 1 )) | head -1`
wait ${!}
$(( COUNTER+=1 ))
if [ "$COUNTER" -ge ${#COLORS[@]} ]; then
# remove all color locks
rm /home/lior/Desktop/mygrep_*
wait ${!}
fi
done
# mark this color as used
touch /home/lior/Desktop/mygrep_$NUM
wait ${!}
# lets go!
GREP_COLORS="mt=${COLORS[$NUM]}" grep "$@"
}
私はこのエイリアスを次のように使用しています:
ll | mg c | mg o | mg n | mg f
結果はかなりクールです。ただし、毎回若干異なるエラーがいくつかあります。ここにいくつかのスクリーンショットがあります:
シェルが各パイプコマンドを実行するときに、前の関数はまだ実行を完了していません。存在しないファイルを削除しようとします。他のcommand not found
エラーがどこから発生しているかはわかりません。
ご覧のとおり、ファイル操作を完了させるためにいくつかのwait
コマンドを入れましたが、これはあまりうまく機能していないようです。もう1つ試したことは、共有メモリ/dev/shm
を使用することですが、同じような結果が得られました。
希望する結果を得るにはどうすればよいですか?
注意:
使用したい機能がたくさんあり、パイプの間に他のロジックを挿入するつもりなので、grepコマンドを単純にラップする答えを探しています。したがって、すべての検索語を一度に提供したくありません。他の「grepのような」ツールも探していません。申し訳ありません @ terdon 素晴らしいPerlの提案をすでに投稿している人。
ここに別のアプローチがあります。別の回答で すでに投稿されています の小さなPerlスクリプトがあり、ユーザーが指定したパターンを異なる色で強調表示します。スクリプトのわずかに変更されたバージョンは、grep
のように動作します。
#!/usr/bin/env Perl
use Getopt::Std;
use strict;
use Term::ANSIColor;
my %opts;
getopts('hic:l:',\%opts);
if ($opts{h}){
print<<EoF;
Use -l to specify the pattern(s) to highlight. To specify more than one
pattern use commas.
-l : A Perl regular expression to be colored. Multiple expressions can be
passed as comma separated values: -l foo,bar,baz
-i : makes the search case sensitive
-c : comma separated list of colors;
EoF
exit(0);
}
my $case_sensitive=$opts{i}||undef;
my @color=('bold red','bold blue', 'bold yellow', 'bold green',
'bold Magenta', 'bold cyan', 'yellow on_blue',
'bright_white on_yellow', 'bright_yellow on_red', 'white on_black');
if ($opts{c}) {
@color=split(/,/,$opts{c});
}
my @patterns;
if($opts{l}){
@patterns=split(/,/,$opts{l});
}
else{
$patterns[0]='\*';
}
# Setting $| to non-zero forces a flush right away and after
# every write or print on the currently selected output channel.
$|=1;
while (my $line=<>)
{
my $want=0;
for (my $c=0; $c<=$#patterns; $c++){
if($case_sensitive){
if($line=~/$patterns[$c]/){
$line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ge;
$want++;
}
}
else{
if($line=~/$patterns[$c]/i){
$line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ige;
$want++;
}
}
}
print STDOUT $line if $want>0;
}
そのスクリプトをcgrep
としてPATH
のどこかに保存し、実行可能にすると、最大10の異なるパターンを指定でき、それぞれ異なる色で印刷されます。
$ cgrep -h
Use -l to specify the pattern(s) to highlight. To specify more than one
pattern use commas.
-l : A Perl regular expression to be colored. Multiple expressions can be
passed as comma separated values: -l foo,bar,baz
-i : makes the search case sensitive
-c : comma separated list of colors;
パイプでのgrep
の呼び出しはそれぞれ別のシェルで実行されるため、それらの間で状態を渡す必要があります。次の解決策は、カラーインデックスを保持するファイルと、同時呼び出しが同じ値を読み取らないようにするロックファイルでそれを処理する大まかな方法です。
#!/usr/bin/env bash
color_index_file=~/.gitcolor
color_index_lock_file=/tmp/$(basename $0)
colors=()
for index in {31..34}
do
colors+=("01;$index")
done
until mkdir "$color_index_lock_file" 2>/dev/null
do
:
done
color_index=$(($(cat "$color_index_file" || echo 0) + 1))
if [[ $color_index -ge ${#colors[@]} ]]
then
color_index=0
fi
printf "$color_index" > "$color_index_file"
rmdir "$color_index_lock_file"
GREP_COLORS="mt=01;${colors[$color_index]}" grep --color=always "$@"
コピーにcgrep
という名前を付けて、PATH
に配置したと想定してテストします。
echo foobarbaz | cgrep foo | cgrep bar | cgrep baz
正規表現に慣れている場合は、grcとgrcatを調べてみてください。 grcはgrcatを呼び出します。
grcatは、各色で表示されるテキストに一致する正規表現を追加できる構成ファイルを使用します。他にも多くのオプションがあります。デフォルトでは、システムログファイルが色分けされます。
最終的なスクリプトで何を念頭に置いているかによって、1つのコマンドだけで出力を色分けできる場合があります。
トリックは、データソースの各「フィールド」の正規表現を正しく指定することです。データの構造が比較的均一であれば、これははるかに簡単です。
前回試してみたが、それほど遠くまでは行かなかったが、正規表現の方が以前よりも少し上手なので、もう一回試してみるかもしれない。
ターミナルデバイスに直接情報(色の変更など)を送信するために使用できるtputコマンドもあります。
どちらのアプローチについても、以下の投稿で取り上げます。これは、findコマンドについて説明しますが、任意のコマンドの出力に適用できます。