解析 Linux

Parsing in Linux

我想解析 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 }' | grep -v '|' | tr '\n' ';'

但它returns输出是这样的

;internal;Compute01;Compute02;nova;;
$  nova availability-zone-list | awk '/^[|] [^|]/{node=} node && /nova-compute/ {s=s ";" node} END{print substr(s,2)}' 
Compute01;Compute02

工作原理:

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

    任何时候一行以 | 开头,后跟 space 后跟一个非 | 的字符,然后将第二个字段保存为节点名称。

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

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

  • END{print substr(s,2)}

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

在 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 = ;
  }

  # 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;

我讨厌单行程序,除了最简单的应用程序。它们不必要地晦涩难懂,它们具有 none 的常用编程支持,并且它们仅存储在终端缓冲区中。明天想做同样的事情吗?你必须重新开始编码

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

$ perl nova-compute.pl command-output.txt
use strict;
use warnings 'all';

my ($node, @nodes);

while ( <> ) {
    $node =  if /^ \| \s* (\w+) /x;
    push @nodes, $node if /nova-compute/;
}

print join(';', @nodes), "\n";

产出

Compute01;Compute02

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