输出的Sed颜色不按预期工作

时间:2017-05-16 15:21:37

标签: regex bash sed

我有以下代码:

#!/bin/bash

reset=$(tput sgr0)
bold=$(tput bold)

red=$(tput setaf 1)
white=$(tput setaf 7)

pattern[0]='[0-9]'
replacement[0]="${white}${bold}&${reset}"

pattern[1]='[a-z]'
replacement[1]="${red}${bold}&${reset}"

args=()
for (( i=0; i < ${#pattern[@]}; i++ )) ; do
    args+=(-e "s/${pattern[i]}/${replacement[i]}/g")
done

echo "asdf1234" | sed "${args[@]}"

输出:

asdfmm1mmm2mmm3mmm4m

即。添加了额外的m个字符,所有字母字符都是红色,数字不会突出显示。

我的愿望是用红色字母和白色数字。我怎么能这样做?

2 个答案:

答案 0 :(得分:1)

它不起作用的原因是白色和粗体的代码包含与第二个模式匹配的字符。 sed在每个输入行上按顺序应用所有模式,例如

echo a | sed -e s/a/b/ -e s/b/c/  # Outputs "c".

您需要的是根据捕获的数据使用具有不同替换的单个表达式,这是可能的。在Perl:

#! /usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

use List::Util qw{ first };
use Term::ANSIColor qw{ color };


my $reset = color('reset');
my $bold  = color('bold');
my $red   = color('red');
my $white = color('white');

my (@pattern, @replacement);

push @pattern, '[0-9]';
push @replacement, "$white$bold";

push @pattern, '[a-z]';
push @replacement, "$red$bold";

my $regex = join '|', map "($_)", @pattern;

my $string = 'asdf1234';

$string =~ s/$regex/
    my $i = first { defined $+[$_] } 1 .. $#+;
    $replacement[$i-1] . "$+$reset"
    /ge;

say $string;

只需将最后一部分更改为

即可
while (my $string = <>) {
    $string =~ s/$regex/
        my $i = first { defined $+[$_] } 1 .. $#+;
        $replacement[$i-1] . "$+$reset"
        /ge;

    print $string;
}

使其处理stdin或作为参数给出的文件。

答案 1 :(得分:1)

试试这样:

#!/bin/bash

reset=$(tput sgr0)     # \001
bold=$(tput bold)      # \002

red=$(tput setaf 1)    # \003
white=$(tput setaf 7)  # \004

pattern[0]='[0-9]'
replacement[0]=$'\004\002&\001'

pattern[1]='[a-z]'
replacement[1]=$'\003\002&\001'

args=()
for (( i=0; i < ${#pattern[@]}; i++ )) ; do
    args+=(-e "s/${pattern[i]}/${replacement[i]}/g")
done

echo "asdf1234" | sed "${args[@]}" \
    | sed -e $'s/\001/'$reset'/g'  \
          -e $'s/\002/'$bold'/g'   \
          -e $'s/\003/'$red'/g'    \
          -e $'s/\004/'$white'/g'

我的系统输出:

screenshot