여러 가지 빛깔의 Grep


30

각 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문자는 빨간색으로 강조 표시됩니다.

이 예제가 작동하려면 --color=alwaysgrep 명령 을 항상 가지고 있어야 합니다. 나는 이것을 .bashrc grep에 항상 설정 하도록 grep을 설정했습니다 .

export GREP_OPTIONS='--color=always'


내가 달성하려는 것은이 기능을 별칭으로 감싸서 매번 호출 grep하고 다른 GREP_COLORS값을 가질 수 있도록하는 것 입니다. 나는 각각의 새로운 파이프 그렙에 대해 여러 개의 셸을 고려해야한다는 것을 이해하고 있으며 이미 사용 된 것을 나타내는 일부 파일 (각 색상마다 하나씩)을 만들어서 이것을 극복하려고 노력하고 있습니다.

나는 약간의 시도를했지만 이상하게도 이것은 "최고"로 작동하는 것으로 보인다. 나는 이것을 내 안에있다 .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, 파일 조작을 완료하려고 시도 하는 명령을 넣었 지만 제대로 작동하지 않는 것 같습니다. 내가 이미 시도한 또 다른 것은 공유 메모리를 사용하는 /dev/shm것이지만 비슷한 결과를 얻었습니다.

원하는 결과를 얻으려면 어떻게해야합니까?

노트 :

grep 명령을 사용하기를 원하고 파이프 사이에 다른 논리를 삽입하려는 grep 명령을 간단히 감싸는 대답을 찾고 있으므로 모든 검색어를 한 번에 제공하고 싶지 않습니다. 또한 다른 "grep like"도구를 찾고 있지 않습니다. 이미 멋진 펄 제안을 게시 한 @terdon 에게 죄송합니다 .


첫 번째 예는 나머지 부분에서 설명하고있는 것과 일치하지 않습니다.
Bernhard

@bernhard 나는 당신이 무슨 뜻인지 이해하지 못합니다. 내 의도는 배관을 사용하여 더 큰 명령의 일부로 내 별칭을 사용하는 것입니다 ... 당신이 말하는 모순을 알려주십시오 ...
Lix

파이프 외부에서도 별칭을 사용하고 싶다고 생각했습니다. 어쨌든, 첫 번째 예는 나를 위해 작동하지 않습니다. 시도 했습니까 alias mg="mygrep; grep"?
Bernhard

@ Bernhard-우분투 12.04 상자에서 일하고 있습니다. 약간의 차이점이 있다면 놀라지 않을 것입니다 ... 나는 당신의 제안을 시도했습니다. 문제는 그 mygrep;자체로 새로운 명령으로 바뀌고 데이터 스트림이 손실 된다는 것입니다 . 에서 들어오는 파이프는 grep하지 않고 ls전달됩니다 mygrep;. 적어도 그것이 내가 이해하는 방법입니다.
Lix

@Bernhard-아 .. 왜 당신에게 효과가 없는지 알고 있습니다. --color=always모든 grep 명령 을 가지고 있는지 확인해야 합니다. 전 세계적으로 설정했습니다 .bashrc. 게시물을 수정했습니다.
Lix

답변:


6

다른 접근법이 있습니다. 다른 답변으로 이미 게시 한 작은 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;

5

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

실제로 유지 관리해야하는 유일한 변수는 COLOR_INDEXGREP_COLORS입니다. 나는 함수의 끝에서 성공하지 않고 이것을 내보내려고했습니다. 그게 무슨 뜻이야? 간단하게 export VAR, 맞습니까?
Lix

아, 그리고 그렇습니다 COLOR_TOGGLE. 그것을 잡아 주셔서 감사합니다 :)
Lix

1
@ l0b0 내보내기도 작동하지 않습니다. 실제로 질문에 대답 할 때까지 downvote해야합니다.
Bernhard

@Bernhard 이것이 당신을 위해 작동합니까?
l0b0

입력 해 주셔서 감사합니다! 나는 당신의 통합 한 grep "$@"기능을 실행 한 다음 grep을 할 수있는 별명을 정리 - 제안.
Lix

1

정규 표현식에 익숙하다면 grc 및 grcat을 확인하십시오. grc는 grcat을 호출합니다.

grcat은 구성 파일을 사용하여 각 색상으로 표시 할 텍스트와 일치시키는 정규식을 추가 할 수 있습니다. 또한 다른 많은 옵션이 있습니다. 기본적으로 시스템 로그 파일을 채색합니다.

최종 스크립트에 대해 생각한 내용에 따라 하나의 명령으로 출력을 채색 할 수 있습니다.

트릭은 데이터 소스의 각 "필드"에 대해 정규 표현식을 올바르게 지정하는 것입니다. 데이터의 구조가 비교적 균일하면 훨씬 쉽습니다.

마지막으로 시도했을 때 너무 멀리 가지 않았지만 이전보다 정규 표현식에 조금 더 좋기 때문에 다시 시도해야 할 수도 있습니다.

터미널 장치에 직접 정보 (색상 변경 등)를 보내는 데 사용할 수있는 tput 명령도 있습니다.

두 가지 방법 모두 아래 게시물에 포함되어 있습니다. find 명령에 대해 설명하지만 모든 명령의 출력에 적용 할 수 있습니다.

컬러 FIND 출력?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.