【问题标题】:Parsing in Linux在 Linux 中解析
【发布时间】:2016-11-09 10:21:28
【问题描述】:

我想在 open-stack 命令输出中解析计算区域,如下所示

+-----------------------+----------------------------------------+
| Name                  | Status                                 |
+-----------------------+----------------------------------------+
| internal              | available                              |
| |- controller         |                                        |
| | |- nova-conductor   | enabled :-) 2016-07-07T08:09:57.000000 |
| | |- nova-consoleauth | enabled :-) 2016-07-07T08:10:01.000000 |
| | |- nova-scheduler   | enabled :-) 2016-07-07T08:10:00.000000 |
| | |- nova-cert        | enabled :-) 2016-07-07T08:10:00.000000 |
| Compute01             | available                              |
| |- compute01          |                                        |
| | |- nova-compute     | enabled :-) 2016-07-07T08:09:53.000000 |
| Compute02             | available                              |
| |- compute02          |                                        |
| | |- nova-compute     | enabled :-) 2016-07-07T08:10:00.000000 |
| nova                  | not available                          |
+-----------------------+----------------------------------------+

我想解析结果如下,只取具有 nova-compute 的节点

Compute01;Compute02

我使用了以下命令:

nova availability-zone-list | awk 'NR>2 {print $2}' | grep -v '|' | tr '\n' ';'

但它会像这样返回输出

;internal;Compute01;Compute02;nova;;

【问题讨论】:

  • @Jens 结果与 ;internal;Compute01;Compute02;nova;; 相同
  • @Jens 这确实有效 nova availability-zone-list | awk 'NR>2 {打印 $2}' | grep -v '|' |grep -v '内部' |grep -v "nova" | tr '\n' ';'结果为 ;Compute01;Compute02;;。我想输出为';'分开,我不能只排除 nova,内部 bcoz 他们可能是别的东西,我想要一个具有 nova-compute 的节点
  • 您可能应该使用 API 以机器可读的形式获取此输出。也许提交愿望清单错误报告以将其添加到nova 客户端。

标签: linux perl shell parsing openstack-nova


【解决方案1】:

在 Perl 中(写得比实际需要的更冗长):

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

my $node; # Store current node name
my @compute_nodes; # Store known nova-compute nodes

while (<>) { # Read from STDIN
  # If we find the start of line, followed by a pipe, a space and
  # a series of word characters...
  if (/^\| (\w+)/) {
    # Store the series of word characters (i.e. the node name) in $node
    $node = $1;
  }

  # If we find a line that contains "nova-compute", add the current
  # node name in @compute_nodes
  push @compute_nodes, $node if /nova-compute/;
}

# Print out all of the values in @compute_nodes    
say join ';', @compute_nodes;

【讨论】:

    【解决方案2】:

    我讨厌单行程序,除了最简单的应用程序。它们是不必要的神秘,它们没有通常的编程支持,它们只存储在终端缓冲区中。明天想做同样的事情吗?你必须重新开始编码

    这是一个 Perl 解决方案。运行它

    $ perl nova-compute.pl command-output.txt
    
    use strict;
    use warnings 'all';
    
    my ($node, @nodes);
    
    while ( <> ) {
        $node = $1 if /^ \| \s* (\w+) /x;
        push @nodes, $node if /nova-compute/;
    }
    
    print join(';', @nodes), "\n";
    

    输出

    Compute01;Compute02
    

    现在所有这些都保存在磁盘上。它可以随时再次运行,修改以获得类似的结果,或者如果你弄错了就修复它。它也是可读的。没有比赛

    【讨论】:

      【解决方案3】:
      $  nova availability-zone-list | awk '/^[|] [^|]/{node=$2} node && /nova-compute/ {s=s ";" node} END{print substr(s,2)}' 
      Compute01;Compute02
      

      它是如何工作的:

      • /^[|] [^|]/{node=$2}

        只要一行以| 开头,后跟空格,后跟一个不是| 的字符,则将第二个字段保存为节点名称。

      • node &amp;&amp; /nova-compute/ {s=s ";" node}

        如果node 非空且当前行包含nova-compute,则将node 附加到字符串s

      • END{print substr(s,2)}

        在我们读完所有行之后,打印出字符串s减去它的第一个字符,这是一个多余的;

      【讨论】:

      • 它正在工作,感谢您的描述它很有帮助
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多