2016-02-27 2 views
3

У меня есть файл с разделителями разделов, для которого я хочу условно выделить определенные столбцы или определенные значения.Выделите значения, разделенные вкладками, на основе нескольких правил

Пример исходного файла:

wn  name   Building Name  8  Desc  char  -> bl 
wo  bl_id!*  Building Code  8     char 

Я хочу:

  • положить в желтый содержимое 2-го столбца, когда имя суффиксом «!»
  • положить в голубой цвет содержание 2-го столбца и зеленым содержимым 7 колонки, когда есть такая 7-й столбец
  • поставить немного «*» знак в красном, во 2-й колонке

и еще пару таких правил.

В настоящее время я сделать это таким образом:

cat file.tsv 
    | sed -r 's/^([^\t]*)\t([^\t]*)!/\1\t\x1b[33m\2!\x1b[0m/' \ 
    | sed -r 's/^^([^\t]*)\t([^\t]*)\t(.*)\t-> ([^\t]+)/\1\t\x1b[36m\2\x1b[0m\t\3\t-> \x1b[32m\4\x1b[0m/' \ 
    | sed -r 's/\*/\x1b[31;1m&\x1b[0m/' 

Но это довольно сложно читать и обновлять.

Есть ли лучший способ? Я совершенно уверен, но какой?

Есть ли такие вещи, как GRC или Supercat? Хотя, я должен признать, что у меня есть довольно важное ограничение: я хотел бы, чтобы решение работало из коробки в Cygwin. Не хотите, чтобы скомпилировать инструменты там - по соображениям переносимости моего кода.

Можете ли вы рассказать о том, как улучшить код, чтобы получить такую ​​«подсветку» функциональности?

ответ

1

Вы можете сделать это с GNU AWK, как это (col.awk):

function colText (text, col) { 
    return sprintf("\033[%sm%s\033[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 $2 
$2 ~ /\*/ {gsub(/\*/, red("*"), $2); } 

# cyan if col 7 present 
NF == 7 {print $1, cyan($2), $3, $4, $5, $6, green($7) ; 
     next;} 

# yellow col2 if there is a ! 
$2 ~ /!/ {print $1, yellow($2), $3, $4, $5, $6, $7 } 

использовать его как это gawk -f col.awk file.tsv

+0

Обратите внимание, что это немного страшнее, чтобы адаптироваться в том смысле, что sed никогда не подавлял строки и не дублировал их. С awk-скриптом такие вещи могут случиться, если мы недостаточно осторожны ... – user3341592

1

Вы могли бы сделать сценарий более удобным для чтения с помощью переменной оболочки (и 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]*)!/\1\t'"$YELLOW"'\2!'"$COLOR_OFF"'/' \ 
    | sed -r 's/^([^\t]*)\t([^\t]*)\t(.*)\t-> ([^\t]+)/\1\t'"$CYAN"'\2'"$COLOR_OFF"'\t\3\t-> '"$GREEN"'\4'"$COLOR_OFF"'/' \ 
    | sed -r 's/\*/'"$BOLD_RED"'&'"$COLOR_OFF"'/' 

Кроме того, вы могли бы сделать переменное для регулярного выражения куска, который все, кроме вкладки, например,

NO_TABS='([^\t]*)' 

Кстати, один из sed выражений повторил ^ (опечатка).

+0

Ваше предложение уже является улучшение моего кода (и спасибо за опечатку), но я согласен с ответом Ларса, который позволяет более легко определять правила выделения, чем в sed. Спасибо за вашу помощь!! – user3341592

+0

В какой оболочке (доступной от Cygwin?) Можно проверить проблемы с переносимостью? IOW, в котором они делают коды, такие как '\ e [31m' не работают? – user3341592

+0

Не все терминалы * поддержка * цвета ANSI. Откладывая это на базу данных терминала, пользователи могут подавлять цвета, если они выбирают. –

Смежные вопросы