【问题标题】:extract strings from a service response and group values basis on keys from that response从服务响应中提取字符串,并根据该响应中的键对值进行分组
【发布时间】:2018-10-06 13:43:21
【问题描述】:

我有一个服务(http://localhost:8080/tester),当我调用它时,它会给我以下响应。为了清楚起见,我已经缩短了格式。

modified=false
ver=10
PATH=/doc/path/abc
    Servers:3
    pri:{0=1, 1=2, 2=3, 3=4, 4=5, 5=6, 6=7, 7=8, 8=1, 9=2, 10=3, 11=4, 12=5, 13=6, 14=7, 15=8, 17=2, 16=1, 19=4, 18=3, 21=6, 20=5, 23=8, 22=7, 25=2, 24=1, 27=4, 26=3, 29=6, 28=5, 31=8, 30=7, 34=3, 35=4, 32=1, 33=2, 38=7, 39=8, 36=5, 37=6, 42=3, 43=4, 40=1}
    sec:{0=2, 1=3, 2=4, 3=5, 4=6, 5=7, 6=8, 7=1, 8=3, 9=4, 10=5}
PATH=/doc/path/pqr
    Servers:3
    pri:{0=1, 1=2, 2=3, 3=4, 4=5, 5=6, 6=7, 7=8, 8=1, 9=2, 10=3, 11=4, 12=5, 13=6, 14=7, 15=8, 17=2, 16=1, 19=4, 18=3, 21=6, 20=5, 23=8, 22=7, 25=2, 24=1, 27=4, 26=3, 29=6, 28=5, 31=8, 30=7, 34=3, 35=4, 32=1, 33=2, 38=7, 39=8, 36=5, 37=6, 42=3, 43=4, 40=1}
    sec:{0=2, 1=3, 2=4, 3=5, 4=6, 5=7, 6=8, 7=1, 8=3, 9=4, 10=5}

我需要阅读此响应并提取 prisec 的值,但仅限于 PATH=/doc/path/abc。现在prisec的格式是这样的:

{value1=key1, value2=key2, value3=key2, value4=key1}

每个唯一键在prisec 列表中都可以有多个值。现在我需要同时读取prisec 列表,并为pri 列表创建两个文件p.txts.txtsec 列表,方法是基于唯一键对值进行分组,如下所示:

p.txt 这里的键和值来自pri 列表。

{key1=[value1, value2, value3, value4, value5, value6, value7, value8], key2=[value9, value10, value11, value12, value13, value14]}

s.txt 这里的键和值来自sec 列表。

{key1=[value1, value2, value3, value4, value5, value6, value7, value8], key2=[value9, value10, value11, value12, value13, value14]}

我不知道如何仅提取 prisec 的值以获取 PATH=/doc/path/abc 并通过对每个唯一键的值进行分组来制作相应的文件 p.txts.txt,就像上述格式一样。

DATA=$(wget -O - -q -t 1 http://localhost:8080/tester);
echo $DATA
# extract pri and sec here and then group values basis on unique keys 
# and generate files accordingly.
while IFS= read -r $DATA
do
   echo "$line"
done

【问题讨论】:

  • 哎呀。选择 Perl 还是 Python?
  • 是的 perl 或 python 也是一个选项。肯定会很难解析这些字符串并通过 linux 将其格式化。

标签: python linux perl awk sed


【解决方案1】:

Welp,我的 Perl 有点生疏了,但这里有一些东西可以帮助您入门。它解析整个数据结构,然后提取命令行中给出的部分。我不知道你正在使用哪个版本的 Perl,或者你是否有能力安装模块,所以我尽可能保持它的简单。

#!/usr/bin/perl

use strict;
use warnings;

unless (@ARGV >= 2) {
  die "USAGE: $0 path key=/path/to/key.txt ..\n";
}

our $WANTED_PATH = $ARGV[0];
our %WANTED_KEYS = map split(/=/, $_, 2), @ARGV[1..$#ARGV];

my $data = parse(*STDIN)->{PATH}{$WANTED_PATH}
  or die "FATAL: Path <$WANTED_PATH> not found\n";

while (my ($key, $file) = each %WANTED_KEYS) {
  unless (exists $data->{$key}) {
    warn "Key <$key> not found\n";

    next;
  }

  write_file($file, $data->{$key});

  print "Wrote key <$key> to file <$file>\n";
}

sub parse {
  my ($fh, $wanted) = @_;

  # contains the current subsection of the data being parsed
  my $current_path;

  my %data = (PATH => {});
  while (my $line = <$fh>) {
    chomp $line;

    next unless $line =~ /\S/;

    if ($line =~ s/^\s+//) {
      if ($current_path) {
        my ($key, $value) = split /\s*:\s*/, $line, 2;

        if (exists $WANTED_KEYS{$key}) {
          $value = parse_pairs($value);
        }

        $data{PATH}{$current_path}{$key} = $value;
      }
    }
    else {
      my ($key, $value) = split /\s*=\s*/, $line, 2;

      if ($key eq 'PATH') {
        $data{$key}{$current_path = $value} = {};
      }
      else {
        $data{$key} = $value;
      }
    }
  }

  return \%data;
}

sub parse_pairs {
  my ($pairs) = @_;

  my %data;
  while ($pairs =~ /(\d+)\s*=\s*(\d+)/g) {
    push @{ $data{$2} ||= [] }, $1;
  }

  return \%data;
}

sub write_file {
  my ($file, $data) = @_;

  open(my $fh, '>', $file)
    or die "FATAL: Unable to open file <$file> for writing: $!\n";

  print {$fh} '{';
  print {$fh} join ', ',
    map sprintf('%s=[%s]', $_, join(', ', sort @{ $data->{$_} })),
    sort keys %$data;
  print {$fh} '}';

  close($fh);
}

像这样使用它:

wget -O- -q -t1 http://localhost:8080/tester |
  ./tester.pl /doc/path/abc pri=p.txt sec=s.txt

【讨论】:

  • 是的,它抱怨这个模块LWP::Simple module。检查如何在 ubuntu 16 上安装此模块。如果您知道步骤,请告诉我
  • @user5447339 apt-get install libwww-perl 应该可以解决问题。我还可以对其进行修改以在输入上接受wget 的输出。如果您愿意,请告诉我。
  • 是的,我认为 wget 会很棒
  • @user5447339 已更新!
  • 我收到此错误:Can't use string ("{0=2, 1=3, 2=4, 3=5, 4=6, 5=7, 6"...) as a HASH ref while "strict refs" in use at ./tester.pl line 83. 我认为这是 `map sprintf('%s=[%s]', $_, join(', ', sort @{ $数据->{$_} })),`
猜你喜欢
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
  • 2018-06-11
  • 1970-01-01
  • 2014-08-30
  • 1970-01-01
  • 2020-05-20
  • 1970-01-01
相关资源
最近更新 更多