我希望能够将任何命令行程序的输出传递给将其转换为json的命令。
例如,我未知的程序可以接受目标列,定界符和输出字段名称
# select columns 1 and 3 from the output and convert it to simple json
netstat -a | grep CLOSE_WAIT | convert_to_json 1,3 name,other
并会生成如下内容:
[
{"name": "tcp4", "other": "31"},
{"name": "tcp4", "other": "0"}
...
]
我正在寻找适用于任何程序的东西,而不仅仅是
netstat
!我愿意安装任何第三方工具/开源项目,并且倾向于在linux/osx上运行-不必是bash脚本解决方案,可以用node,perl,python等编写。
编辑:我当然愿意传递使它正常工作所需的更多信息,例如一个定界符或多个定界符-我只是想避免在命令行中进行显式解析,并拥有该工具去做。
最佳答案
过滤 STDIN 以构建 json 变量
介绍
由于终端是一种非常特殊的界面,具有等宽字体,
工具是为了在这个终端上监控而构建的,许多输出可能非常
难以解析:netstat
输出是一个很好的示例:
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 13947569 @/tmp/.X11-unix/X1
unix 2 [ ] DGRAM 8760 /run/systemd/notify
unix 2 [ ACC ] SEQPACKET LISTENING 8790 /run/udev/control
如果某些行包含空白字段,则不能简单地在空格上拆分。
因此,requestet 脚本
convert_to_json
将发布在此的最底部。使用
awk
进行简单的基于空间的分割通过使用
awk
,你可以使用很好的语法:netstat -an |
awk '/CLOSE_WAIT/{
printf " { \42%s\42:\42%s\42,\42%s\42:\42%s\42},\n","name",$1,"other",$3
}' |
sed '1s/^/[\n/;$s/,$/\n]/'
使用
perl
进行简单的基于空间的拆分,但使用 json 库但是这种 perl 方式更灵活:
netstat -an | perl -MJSON::XS -ne 'push @out,{"name"=>,$1,"other"=>$2} if /^(\S+)\s+\d+\s+(\d+)\s.*CLOSE_WAIT/;END{print encode_json(\@out)."\n";}'
或相同但 split ;
netstat -an |
perl -MJSON::XS -ne '
push @out,{"name"=>,$1,"other"=>$2} if
/^(\S+)\s+\d+\s+(\d+)\s.*CLOSE_WAIT/;
END{print encode_json(\@out)."\n";
}'
或打印精美:
netstat -an | perl -MJSON::XS -ne '
push @out,{"name"=>,$1,"other"=>$2} if /^(\S+)\s+\d+\s+(\d+)\s.*CLOSE_WAIT/;
END{$coder = JSON::XS->new->ascii->pretty->allow_nonref;
print $coder->encode(\@out);}'
最后,我喜欢这个不是基于 regex 的版本:
netstat -an | perl -MJSON::XS -ne '
do {
my @line=split(/\s+/);
push @out,{"name"=>,$line[0],"other"=>$line[2]}
} if /CLOSE_WAIT/;
END{
$coder = JSON::XS->new->ascii->pretty->allow_nonref;
print $coder->encode(\@out);
}'
但是你可以在 perl 脚本中运行命令:
perl -MJSON::XS -e '
open STDIN,"netstat -an|";
my @out;
while (<>){
push @out,{"name"=>,$1,"other"=>$2} if /^(\S+)\s+\d+\s+(\d+)\s.*CLOSE_WAIT/;
};
print encode_json \@out;'
这可能成为一个基本的原型(prototype):
#!/usr/bin/perl -w
use strict;
use JSON::XS;
my $coder = JSON::XS->new->ascii->pretty->allow_nonref;
$ENV{'LANG'}='C';
open STDIN,"netstat -naut|";
my @out;
my @fields;
my $searchre=":";
$searchre = shift @ARGV if @ARGV;
while (<>){
map { s/_/ /g;push @fields,$_; } split(/\s+/) if
/^Proto.*State/ && s/\sAddr/_Addr/g;
do {
my @line=split(/\s+/);
my %entry;
for my $i (0..$#fields) {
$entry{$fields[$i]}=$line[$i];
};
push @out,\%entry;
} if /$searchre/;
}
print $coder->encode(\@out);
(没有参数,这将转储整个
netstat -uta
,但您可以将任何搜索字符串作为参数,例如 CLOSE 或 IP。)位置参数,
netstat2json.pl
这种方法可以与
netcat
之外的许多其他工具一起使用,其中一些更正:
#!/usr/bin/perl -w
use strict;
use JSON::XS;
my $coder = JSON::XS->new->ascii->pretty->allow_nonref;
$ENV{'LANG'}='C';
open STDIN,"netstat -nap|";
my ( $searchre ,@out,%fields)=( "[/:]" );
$searchre = shift @ARGV if @ARGV;
while (<>){
next if /^Active\s.*\)$/;
/^Proto.*State/ && do {
s/\s(name|Addr)/_$1/g;
my @head;
map { s/_/ /g;push @head,$_; } split(/\s+/);
s/_/ /g;
%fields=();
for my $i (0..$#head) {
my $crt=index($_,$head[$i]);
my $next=-1;
$next=index($_,$head[$i+1])-$crt-1 if $i < $#head;
$fields{$head[$i]}=[$crt,$next];
}
next;
};
do {
my $line=$_;
my %entry;
for my $i (keys %fields) {
my $crt=substr($line,$fields{$i}[0],$fields{$i}[1]);
$crt=~s/^\s*(\S(|.*\S))\s*$/$1/;
$entry{$i}=$crt;
};
push @out,\%entry;
} if /$searchre/;
}
print $coder->encode(\@out);
Proto.*State
(特定于 netcat
) 这可以使用参数运行,就像以前一样:
./netstat2json.pl CLOS
[
{
"Local Address" : "127.0.0.1:31001",
"State" : "CLOSE_WAIT",
"Recv-Q" : "18",
"Proto" : "tcp",
"Send-Q" : "0",
"Foreign Address" : "127.0.0.1:55938",
"PID/Program name" : "-"
},
{
"Recv-Q" : "1",
"Local Address" : "::1:53816",
"State" : "CLOSE_WAIT",
"Send-Q" : "0",
"PID/Program name" : "-",
"Foreign Address" : "::1:631",
"Proto" : "tcp6"
}
]
空字段不会破坏变量赋值:
./netstat2json.pl 1000.*systemd/notify
[
{
"Proto" : "unix",
"I-Node" : "33378",
"RefCnt" : "2",
"Path" : "/run/user/1000/systemd/notify",
"PID/Program name" : "-",
"Type" : "DGRAM",
"Flags" : "[ ]",
"State" : ""
}
]
注意! 此修改版本使用
netstat
参数运行 -nap
以获取 PID/Program name
字段。如果不是由 super 用户
root
运行,您可以在 STDERR
上成为以下输出:(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
你可以避免它们
netstat2json.pl 2>/dev/null
, root
或使用 sudo
或 #6
,将 "netstat -nap|"
更改为 "netstat -na|"
。 convert_to_json.pl
perl 将 STDIN 转换为 json 的脚本。有
convert_to_json.pl
perl 脚本,严格按照要求:作为 netstat -an | grep CLOSE | ./convert_to_json.pl 1,3 name,other
运行#!/usr/bin/perl -w
use strict;
use JSON::XS;
my $coder = JSON::XS->new->ascii->pretty->allow_nonref;
my (@fields,@pos,@out);
map {
push @pos,1*$_-1
} split ",",shift @ARGV;
map {
push @fields,$_
} split ",",shift @ARGV;
die "Number of fields don't match number of positions" if $#fields ne $#pos;
while (<>) {
my @line=split(/\s+/);
my %entry;
for my $i (0..$#fields) {
$entry{$fields[$i]}=$line[$pos[$i]];
};
push @out,\%entry;
}
print $coder->encode(\@out);
关于json - 通过终端中的列将任意输出转换为json?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40246134/