У меня есть скрипт, который получает некоторые данные с веб-сайта. Данные поступают в формате JSON, и сайт предлагает возможность «свести» вывод JSON в один объект JSON или оставить его в виде нескольких объектов.
Сценарий имеет параметры, позволяющие преобразовывать данные JSON в YAML (независимо от того, сведены они или нет) или оставлять их в формате JSON.
Кроме того, скрипт раскрашивает значения в обоих форматах.
Чтобы выполнить раскраску, у меня в настоящее время есть 2 функции: одна для раскраски JSON и одна для раскраски YAML.
Сама раскраска достигается с помощью Term::ANSIColor путем поиска и замены текста либо в скаляре, либо в массиве, в зависимости от того, в каком формате вывода находятся данные.
Я хотел бы свести это к одной функции, чтобы уменьшить дублирование кода, но я не знаю, как это сделать.
Для ясности, для ясности основное внимание в этом вопросе уделяется тому, как сделать одну из функций раскрашивания многоразовой, чтобы она могла работать как с выводом YAML, так и с выводом JSON. Поскольку шаблоны поиска очень похожи, а шаблоны замены идентичны, мне кажется, что это должно быть очень легко сделать, но я не знаю, как это сделать.
use JSON;
use YAML::Tiny;
sub colorize_yaml
{
my $OUTPUT = shift;
my $OPTIONS = shift;
if (ref $OUTPUT eq 'SCALAR')
{
foreach (${$OUTPUT})
{
# Hide this if debugging is disabled, else show it and color it
if (!$OPTIONS->{debug})
{
s{(statusCode|success|dataExist|verumModelObjectName):\ [a-zA-Z0-9]+\n}
{}gxms;
}
else
{
s{(statusCode|success|dataExist|verumModelObjectName):}
{$OPTIONS->{color} ? BOLD YELLOW $1 . ':', BOLD GREEN : $1 . ':'}gxmse;
}
# Colorize 5 segment flat output
s{([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:\ )}
{$OPTIONS->{color} ? BOLD CYAN $1, BOLD YELLOW $2, BOLD MAGENTA $3, BOLD RED $4, RESET $5: $1 . $2 . $3 . $4 . $5}gxmse;
# Colorize 4 segment flat output
s{([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:\ )}
{$OPTIONS->{color} ? BOLD CYAN $1, BOLD YELLOW $2, BOLD MAGENTA $3, RESET $4 : $1 . $2 . $3 . $4}gxmse;
# Colorize 3 segment flat output
s{([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:\ )}
{$OPTIONS->{color} ? BOLD CYAN $1, BOLD YELLOW $2, RESET $3 : $1 . $2 . $3}gxmse;
# Colorize 2 segment flat output
s{([a-zA-Z0-9]+:)([a-zA-Z0-9]+:\ )}
{$OPTIONS->{color} ? BOLD CYAN $1, RESET $2 : $1 . $2}gxmse;
# Colorize values in all output
s{(:\ )}
{$OPTIONS->{color} ? $1 . BOLD GREEN : $1}gxmse;
# Reset colors before newlines so that the next line starts with a clean color pattern.
s{\n}
{$OPTIONS->{color} ? RESET "\n" : "\n"}gxmse;
}
}
else
{
pretty_print_error("WARNING: Unable to colorize YAML output\n", $OPTIONS->{color});
return;
}
return;
}
sub colorize_json
{
my $OUTPUT = shift;
my $OPTIONS = shift;
if (ref $OUTPUT eq 'ARRAY')
{
foreach (@{$OUTPUT})
{
if ($OPTIONS->{debug})
{
s{(statusCode|success|dataExist|verumModelObjectName):}
{$OPTIONS->{color} ? BOLD YELLOW $1 . ':', BOLD GREEN : $1 . ':'}gxmse;
}
else
{
s{(statusCode|success|dataExist|verumModelObjectName):\ [a-zA-Z0-9]+\n}
{}gxms;
}
# Colorize 5 segment flat output
s{^([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:\ .*$)}
{$OPTIONS->{color} ? BOLD CYAN $1, BOLD YELLOW $2, BOLD MAGENTA $3, BOLD RED, $4, RESET $5: $1 . $2 . $3 . $4 . $5}gxmse;
# Colorize 4 segment flat output
s{^([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:\ )}
{$OPTIONS->{color} ? BOLD CYAN $1, BOLD YELLOW $2, BOLD MAGENTA $3, RESET $4 : $1 . $2 . $3 . $4}gxmse;
# Colorize 3 segment flat output
s{^([a-zA-Z0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+:\ )}
{$OPTIONS->{color} ? BOLD CYAN $1, BOLD YELLOW $2, RESET $3 : $1 . $2 . $3}gxmse;
# Colorize 2 segment flat output
s{^([a-zA-Z0-9]+:)([a-zA-Z0-9]+:\ )}
{$OPTIONS->{color} ? BOLD CYAN $1, RESET $2 : $1 . $2}gxmse;
# Colorize values in all output
s{(:\ )}
{$OPTIONS->{color} ? $1 . BOLD GREEN : $1}gxmse;
# Reset colors before newlines so that the next line starts with a clean color pattern.
s{$}
{$OPTIONS->{color} ? RESET '' : ''}gxmse;
}
}
else
{
pretty_print_error("WARNING: Unable to colorize JSON output.\n", $OPTIONS->{color});
return;
}
return;
}
JSON преобразован в YAML
---
message: Success
ObjectList:
-
assetName: xxxxxxxx
backupAsset:
-
backupFlag: xxxxxxxx
fullyCertified: xxxxxxxx
Плоский JSON преобразован в YAML
---
message: Success
verumObjectList:
-
assetName: xxxxxxxx
backupAsset:backupFlag: xxxxxxxx
backupAsset:fullyCertified: xxxxxxxx
JSON (данные в формате JSON удаляются скриптом, чтобы сделать их простым текстом)
assetName: xxxxxxxx
backupFlag: xxxxxxxx
fullyCertified: xxxxxxxx
message: Success
Плоский JSON (данные в формате JSON удаляются скриптом, чтобы сделать их простым текстом)
assetName: xxxxxxxx
backupAsset:backupFlag: xxxxxxxx
backupAsset:fullyCertified: xxxxxxxx
message: Success
Правильный ответ присуждается @zdim, хотя мне пришлось немного изменить код.
Я отправляю свой обновленный код ниже.
use JSON;
use YAML::Tiny;
sub colorize_output
{
my $OUTPUT = shift;
my $OPTIONS = shift;
my $RE_START = $EMPTY;
my $RE_END = q{\ };
if (ref $OUTPUT eq $EMPTY)
{
pretty_print_error("WARNING: Unable to colorize output.\n",
$OPTIONS->{color});
return;
}
elsif (ref $OUTPUT eq 'ARRAY')
{
$RE_START = q{^};
$RE_END = q{\ .*};
}
my $ANCHOR = q{[a-zA-Z0-9]+:};
my $PATTERN = qq{($ANCHOR)};
Readonly my $SEGMENT_LIMIT => 4;
my $VERUM_RE = qr{(statusCode|success|dataExist|verumModelObjectName):}xms;
my ($SEGMENT_2PART_RE, $SEGMENT_3PART_RE, $SEGMENT_4PART_RE, $SEGMENT_5PART_RE)
= map {
qr{$RE_START}xms . ($PATTERN x $ARG) . qr{($ANCHOR$RE_END)}xms
} 1..$SEGMENT_LIMIT;
foreach ((ref $OUTPUT eq 'SCALAR')?${$OUTPUT}:@{$OUTPUT})
{
# Hide this if debugging is disabled, else show it and color it
if (!$OPTIONS->{debug})
{
s{$VERUM_RE\ [a-zA-Z0-9]+}{}gxms;
}
else
{
s{$VERUM_RE}
{$OPTIONS->{color} ? BOLD YELLOW $1 . ':', BOLD GREEN : $1 . ':'}gxmse;
}
# Colorize sections in flat output
if ($OPTIONS->{color})
{
s{$SEGMENT_5PART_RE}
{BOLD CYAN $1, BOLD YELLOW $2, BOLD MAGENTA $3, BOLD RED $4, RESET $5}gxmse;
s{$SEGMENT_4PART_RE}
{BOLD CYAN $1, BOLD YELLOW $2, BOLD MAGENTA $3, RESET $4}gxmse;
s{$SEGMENT_3PART_RE}
{BOLD CYAN $1, BOLD YELLOW $2, RESET $3}gxmse;
s{$SEGMENT_2PART_RE}
{BOLD CYAN $1, RESET $2}gxmse;
# Colorize values in all output
s{(:\ )}{$1 . BOLD GREEN}gxmse;
# Reset colors before newlines or next entry in the list so that
# the next line starts with a clean color pattern.
s{(\n|$)}{RESET $1}gxmse;
}
}
return;
}
do "script.pl";
в верхней части файла модульного теста. Это даст вам функции. Но он также будет запускать код, поэтому архитектура вашего скрипта имеет значение. Пока я просто предложил тест, потому что показать нам ожидаемый результат с терминальными цветами будет ... интересно. ;) - person simbabque   schedule 06.12.2017Yaml::Tiny
Dump
, который заставляет присутствовать символы новой строки. В необработанном формате JSON я сначала преобразовал данные в массив, так как было проще удалить теги JSON из каждой строки вывода по отдельности, чем делать это как одну гигантскую строку. Поскольку мы ничего не удаляем из преобразованного вывода YAML, было проще оставить его как одну гигантскую строку. - person Speeddymon   schedule 06.12.2017YAML::Tiny
задыхается от выделения символов. :-( YAML::PP не задохнется, но, к сожалению, его нельзя установить на этот хост, не прыгая через некоторые огромные корпоративные обручи. - person Speeddymon   schedule 06.12.2017foreach
в этих функциях выглядит одинаково. Это правильно? Вы только спрашиваете, как заставить его обрабатывать либо scalarref, либо arrayref? - person zdim   schedule 06.12.2017use JSON
иuse YAML::Tiny
— это преобразование данных JSON с веб-сайта в формат YAML для отображения данных на экране. Если бы я мог сделать это с данными Perl и при этом получить вывод либо в виде обычного текста, либо в формате YAML, это было бы намного лучше. - person Speeddymon   schedule 06.12.2017s///
немного отличается. - person Speeddymon   schedule 06.12.2017^
... это все? - person zdim   schedule 06.12.2017