根据几条规则突出显示制表符分隔值
Highlight tab-separated values based on a couple of rules
我有一些制表符分隔的文件,我想有条件地突出显示某些列或某些值。
源文件示例:
wn name Building Name 8 Desc char -> bl
wo bl_id!* Building Code 8 char
我想:
- 当名称以“!”为后缀时,将第 2 列的内容填入黄色
- 当有第7列时,用青色表示第2列的内容,用绿色表示第7列的内容
- 在第 2 列中将小“*”标记为红色
以及其他一些此类规则。
目前我是这样做的:
cat file.tsv
| sed -r 's/^([^\t]*)\t([^\t]*)!/\t\x1b[33m!\x1b[0m/' \
| sed -r 's/^^([^\t]*)\t([^\t]*)\t(.*)\t-> ([^\t]+)/\t\x1b[36m\x1b[0m\t\t-> \x1b[32m\x1b[0m/' \
| sed -r 's/\*/\x1b[31;1m&\x1b[0m/'
但是阅读和更新起来相当复杂。
有没有更好的方法?我很确定,但是哪一个?
GRC 或 Supercat 之类的东西是否可行?不过,我不得不承认我有一个非常重要的约束:我希望解决方案在 Cygwin 中开箱即用。不想在那里编译自己的工具——出于我代码的可移植性原因。
您能否提供有关如何改进代码以获得这样的 "highlight" 功能的提示?
您可以通过使用 shell 变量(和 tput
以实现跨终端类型的可移植性)使脚本更具可读性:
BOLD_RED=$(tput setaf 1; tput bold)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
CYAN=$(tput setaf 6)
COLOR_OFF=$(tput sgr0)
cat file.tsv
| sed -r 's/^([^\t]*)\t([^\t]*)!/\t'"$YELLOW"'!'"$COLOR_OFF"'/' \
| sed -r 's/^([^\t]*)\t([^\t]*)\t(.*)\t-> ([^\t]+)/\t'"$CYAN"''"$COLOR_OFF"'\t\t-> '"$GREEN"''"$COLOR_OFF"'/' \
| sed -r 's/\*/'"$BOLD_RED"'&'"$COLOR_OFF"'/'
同样,您可以为除制表符之外的所有内容的正则表达式块创建一个变量,例如
NO_TABS='([^\t]*)'
顺便说一下,其中一个 sed
表达式重复了 ^
(打字错误)。
你可以用 GNU awk 来做,像这样 (col.awk):
function colText ( text, col) {
return sprintf("3[%sm%s3[39;0m", col, text);
}
function yellow( text ){ return colText( text, "33;1" ); }
function cyan ( text ){ return colText( text, "36;1" ); }
function green ( text ){ return colText( text, "32;1" ); }
function red ( text ){ return colText( text, "31;1" ); }
BEGIN {FS=OFS="\t";}
# red * in
~ /\*/ {gsub(/\*/, red("*"), ); }
# cyan if col 7 present
NF == 7 {print , cyan(), , , , , green( ) ;
next;}
# yellow col2 if there is a !
~ /!/ {print , yellow(), , , , , }
这样使用gawk -f col.awk file.tsv
我有一些制表符分隔的文件,我想有条件地突出显示某些列或某些值。
源文件示例:
wn name Building Name 8 Desc char -> bl
wo bl_id!* Building Code 8 char
我想:
- 当名称以“!”为后缀时,将第 2 列的内容填入黄色
- 当有第7列时,用青色表示第2列的内容,用绿色表示第7列的内容
- 在第 2 列中将小“*”标记为红色
以及其他一些此类规则。
目前我是这样做的:
cat file.tsv
| sed -r 's/^([^\t]*)\t([^\t]*)!/\t\x1b[33m!\x1b[0m/' \
| sed -r 's/^^([^\t]*)\t([^\t]*)\t(.*)\t-> ([^\t]+)/\t\x1b[36m\x1b[0m\t\t-> \x1b[32m\x1b[0m/' \
| sed -r 's/\*/\x1b[31;1m&\x1b[0m/'
但是阅读和更新起来相当复杂。
有没有更好的方法?我很确定,但是哪一个?
GRC 或 Supercat 之类的东西是否可行?不过,我不得不承认我有一个非常重要的约束:我希望解决方案在 Cygwin 中开箱即用。不想在那里编译自己的工具——出于我代码的可移植性原因。
您能否提供有关如何改进代码以获得这样的 "highlight" 功能的提示?
您可以通过使用 shell 变量(和 tput
以实现跨终端类型的可移植性)使脚本更具可读性:
BOLD_RED=$(tput setaf 1; tput bold)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
CYAN=$(tput setaf 6)
COLOR_OFF=$(tput sgr0)
cat file.tsv
| sed -r 's/^([^\t]*)\t([^\t]*)!/\t'"$YELLOW"'!'"$COLOR_OFF"'/' \
| sed -r 's/^([^\t]*)\t([^\t]*)\t(.*)\t-> ([^\t]+)/\t'"$CYAN"''"$COLOR_OFF"'\t\t-> '"$GREEN"''"$COLOR_OFF"'/' \
| sed -r 's/\*/'"$BOLD_RED"'&'"$COLOR_OFF"'/'
同样,您可以为除制表符之外的所有内容的正则表达式块创建一个变量,例如
NO_TABS='([^\t]*)'
顺便说一下,其中一个 sed
表达式重复了 ^
(打字错误)。
你可以用 GNU awk 来做,像这样 (col.awk):
function colText ( text, col) {
return sprintf("3[%sm%s3[39;0m", col, text);
}
function yellow( text ){ return colText( text, "33;1" ); }
function cyan ( text ){ return colText( text, "36;1" ); }
function green ( text ){ return colText( text, "32;1" ); }
function red ( text ){ return colText( text, "31;1" ); }
BEGIN {FS=OFS="\t";}
# red * in
~ /\*/ {gsub(/\*/, red("*"), ); }
# cyan if col 7 present
NF == 7 {print , cyan(), , , , , green( ) ;
next;}
# yellow col2 if there is a !
~ /!/ {print , yellow(), , , , , }
这样使用gawk -f col.awk file.tsv