【问题标题】:bash + how to capture word from a long outputbash + 如何从长输出中捕获单词
【发布时间】:2021-11-01 04:33:09
【问题描述】:

我有以下命令的以下输出

zookeeper-shell.sh 19.2.6.4  get /brokers/ids/1010

输出是

Connecting to 19.2.6.4

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
{"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://kafka1.lulu.com:6667"],"rack":"/default-rack","jmx_port":9997,"port":6667,"host":"kafka1.lulu.com","version":4,"timestamp":"1630507307906"}

主要目标是从上面的输出中捕获机器名称kafka1

所以我成功地执行了以下长命令语法

zookeeper-shell.sh 119.2.6.4  get /brokers/ids/1010 | sed s'/\/\// /g' | sed s'/:/ /g' | sed s'/,/ /g' | sed s'/"/ /g' | sed s'/\./ /g'| awk '{for (i=1;i<=NF;i++) print $i}' | grep -i kafka | sort | uniq

结果是:(如预期的结果)

kafka1

情况是我觉得我的方法很糟糕,它太长而且不那么优雅

我们能否得到建议(使用 awk/sed/perl 一个衬里),这比我的语法好得多?

【问题讨论】:

  • 您不需要多个sed 命令。 sed -e 's/x/y/g' -e 's/a/b/g' ...
  • 还有sed -e 's/[:,."]/ /g'

标签: regex language-agnostic


【解决方案1】:

您可以使用以下脚本过滤掉感兴趣的数据,这样可以避免输入长命令行。

use strict;
use warnings;
use feature 'say';

use JSON;

my $data;

while( <> ) {
    next unless /^\{.*?\}$/;   # skip all but JSON string
    
    my $data = from_json($_);  # restore data structure
    my $host = (split('\.',$data->{host}))[0]; # extract info of interest
    
    say $host;                 # output it
}

zookeeper-shell.sh 19.2.6.4 get /brokers/ids/1010 | script.pl 运行。

注意:使脚本可执行chmod +x script.pl 并将其存储在您的$HOME/bin 目录中,该目录添加您的变量$PATH

【讨论】:

    【解决方案2】:

    使用 perl,你可以做到:

    $zookeeper_command | perl -MJSON::PP=decode_json -wnE'/^\{"/ or next; $j = decode_json($_); ($s) = (split /\./, $j->{host})[0]; say $s'
    

    详细说明命令:

    • -MJSON::PP=decode_json => 从 JSON::PP 模块导入 decode_json(这是一个核心模块。
    • /^\{"/ or next; => 跳行看起来不像是 json 字符串。
    • $j = decode_json($_); => 存储到 $j json 字符串的数据结构中。
    • ($s) = (split /\./, $j-&gt;{host})[0]; => 拆分字符串 kafka1.lulu.com 并仅将第一部分存储在 $s 中。

    它也可以写成更短的形式(而且可读性也更差):

    $zookeeper_command | perl -MJSON::PP=decode_json -wnE'say decode_json($_)->{host}=~s/\..*$//r if/^\{"/'
    

    【讨论】:

      【解决方案3】:

      您要解析的文本是 JSON,因此请使用 jq 之类的 JSON 感知工具来完成大部分工作,例如使用cat file,因为我没有你用来产生输出的命令:

      $ cat file | jq -Rr 'fromjson? | .endpoints[]'
      PLAINTEXT://kafka1.lulu.com:6667
      
      $ cat file | jq -Rr 'fromjson? | .endpoints[]' | awk -F'[/.]' '{print $3}'
      kafka1
      

      【讨论】:

        【解决方案4】:

        使用您展示的示例,请尝试按照awk 代码进行尝试。由于我没有 zookeeper 命令,因此我编写了此代码并仅根据您显示的输出对其进行了测试。

        zookeeper-shell.sh 19.2.6.4  get /brokers/ids/1010 | 
        awk '
        /WatchedEvent state/{
          found=1
          next
        }
        found && match($0,/"PLAINTEXT:\/\/[^:]*/){
          print substr($0,RSTART+13,RLENGTH-13)
        }
        ' 
        

        说明:为上述awk代码添加详细说明。

        awk '                                         ##Starting awk program from here.
        /WatchedEvent state/{                         ##Checking condition if line contains WatchedEvent state
          found=1                                     ##Then set found to 1 here.
          next                                        ##next will skip all further statements from here.
        }
        found && match($0,/"PLAINTEXT:\/\/[^:]*/){    ##Checking condition if found is SET then match regex "PLAINTEXT:\/\/[^:]* in match function of awk.
          print substr($0,RSTART+13,RLENGTH-13)       ##Printing sub string of matched regex used in match function above.
        }
        ' 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-28
          • 2023-03-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多