我正在从net::ssh
会话输出到ASA并尝试为每个vpn用户构建一个哈希值,然后将每个哈希值添加到一个数组中。
以下是连接一个用户时的输出。如果有多个用户,则每个用户有更多这样的行:
Username:arozar
Index:654
AssignedIP:10.254.254.7
PublicIP:4.2.2.2
Protocol:AnyConnect-ParentSSL-TunnelDTLS-Tunnel
License:AnyConnectEssentials
Encryption:AnyConnect-Parent:(1)noneSSL-Tunnel:(1)AES256DTLS-Tunnel:(1)AES256
Hashing:AnyConnect-Parent:(1)noneSSL-Tunnel:(1)SHA1DTLS-Tunnel:(1)SHA1
BytesTx:6104355
BytesRx:1191505
GroupPolicy:vpn
TunnelGroup:anyconnect
LoginTime:08:51:55ESTMonNov32014
Duration:1h:08m:48s
Inactivity:0h:00m:00s
NACResult:Unknown
VLANMapping:N/A
VLAN:none
以下是我正在处理的代码:
@ac_array = Array.new
session_output = cmd_session.cmd('show vpn-sessiondb anyconnect')
cmd_session.close
session_output.each_line do |line|
username = line.match(/(?<=Username:)(\w+\S+)/)
assigned_ip = line.match(/(?<=AssignedIP:)(\w+\S+)/)
public_ip = line.match(/(?<=PublicIP:)(\w+\S+)/)
license = line.match(/(?<=License:)(\w+\S+)/)
bytestx = line.match(/(?<=BytesTx:)(\w+\S+)/)
bytesrx = line.match(/(?<=BytesRx:)(\w+\S+)/)
group_policy = line.match(/(?<=GroupPolicy:)(\w+\S+)/)
tunnel_group = line.match(/(?<=TunnelGroup:)(\w+\S+)/)
要将这些匹配放入哈希,我必须这样做:
unless username.nil?
anyconnect_hash = {username:username[0]}
@ac_array.push(anyconnect_hash)
end
unless assigned_ip.nil?
assigned_ip_hash = {assigned_ip:assigned_ip[0]}
@ac_array.push(assigned_ip_hash)
end
unless public_ip.nil?
public_ip_hash = {public_ip:public_ip[0]}
@ac_array.push(public_ip_hash)
end
AND SO ONE DOWN THE LINE for all the matches.....
但我不认为这是最好的方式,在我看来也不是真的有效。我喜欢使用一行unless
语句,并从那里将所有匹配项分配给哈希。
以下是我认为会更好的东西:
unless username.nil? and assigned_ip.nil? and public_ip.nil?
anyconnect_hash = {username:username[0], assigned_ip:assigned_ip[0], public_ip:public_ip[0]}
@ac_array.push(anyconnect_hash)
end
不幸的是,通过这个设置,我得到了“未定义的方法`[]'为nil:NilClass”。
答案 0 :(得分:4)
您可以为每个用户执行以下操作。
<强>代码强>
ATTRIBUTES = [:Username, :AssignedIP, :PublicIP, :License,
:BytesTx, :BytesRx, :GroupPolicy, :TunnelGroup]
def hashify(text)
text.each_line.with_object({}) do |line, h|
ATTRIBUTES.each do |sym|
v = line[/(?<=#{sym.to_s}:)\w+\S+/]
h[sym] = v if v
end
end
end
示例强>
text =
"Username:arozar
AssignedIP:10.254.254.7
PublicIP:4.2.2.2
License:AnyConnectEssentials
BytesTx:6104355
BytesRx:1191505
GroupPolicy:vpn
TunnelGroup:anyconnect"
hashify(text)
#=> {:Username=>"arozar", :AssignedIP=>"10.254.254.7", :PublicIP=>"4.2.2.2",
# :License=>"AnyConnectEssentials", :BytesTx=>"6104355",
# :BytesRx=>"1191505", :GroupPolicy=>"vpn", :TunnelGroup=>"anyconnect"}
备注强>
hashify(text).to_a.map {|k,v| {k=>v} }
)很容易,但考虑一下你是否会用散列更好。这将为您提供每个用户一个哈希的数组。我怀疑,更好的方法是为每个用户提供一个带有一个元素的哈希值。对于示例中的用户,该键值对将是:
"arozar" => { :AssignedIP=>"10.254.254.7", :PublicIP=>"4.2.2.2",
:License=>"AnyConnectEssentials", :BytesTx=>"6104355",
:BytesRx=>"1191505", :GroupPolicy=>"vpn",
:TunnelGroup=>"anyconnect" }
如果示例中显示的哈希值不是您想要的,则需要在正则表达式中修改\w+\S+
[此处与(\w+\S+)
相同]。
这使用方法String#[]的形式,将正则表达式作为参数。
如果你更喜欢,而不是使用正则表达式,你可以写k,v = line.split(':'); u = v[/\w+\S+/]; h[sym] = u if u
,但我更喜欢它。
答案 1 :(得分:3)
好吧,我从以下开始:
text = 'Username:arozar
Index:654
AssignedIP:10.254.254.7
PublicIP:4.2.2.2
Protocol:AnyConnect-ParentSSL-TunnelDTLS-Tunnel
License:AnyConnectEssentials
Encryption:AnyConnect-Parent:(1)noneSSL-Tunnel:(1)AES256DTLS-Tunnel:(1)AES256
Hashing:AnyConnect-Parent:(1)noneSSL-Tunnel:(1)SHA1DTLS-Tunnel:(1)SHA1
BytesTx:6104355
BytesRx:1191505
GroupPolicy:vpn
TunnelGroup:anyconnect
LoginTime:08:51:55ESTMonNov32014
Duration:1h:08m:48s
Inactivity:0h:00m:00s
NACResult:Unknown
VLANMapping:N/A
VLAN:none
'
text.split("\n").reject(&:empty?).map{ |l| l.split(':', 2) }.to_h
# => {"Username"=>"arozar",
# "Index"=>"654",
# "AssignedIP"=>"10.254.254.7",
# "PublicIP"=>"4.2.2.2",
# "Protocol"=>"AnyConnect-ParentSSL-TunnelDTLS-Tunnel",
# "License"=>"AnyConnectEssentials",
# "Encryption"=>
# "AnyConnect-Parent:(1)noneSSL-Tunnel:(1)AES256DTLS-Tunnel:(1)AES256",
# "Hashing"=>
# "AnyConnect-Parent:(1)noneSSL-Tunnel:(1)SHA1DTLS-Tunnel:(1)SHA1",
# "BytesTx"=>"6104355",
# "BytesRx"=>"1191505",
# "GroupPolicy"=>"vpn",
# "TunnelGroup"=>"anyconnect",
# "LoginTime"=>"08:51:55ESTMonNov32014",
# "Duration"=>"1h:08m:48s",
# "Inactivity"=>"0h:00m:00s",
# "NACResult"=>"Unknown",
# "VLANMapping"=>"N/A",
# "VLAN"=>"none"}
如果您的Ruby版本不支持to_h
,请将命令包装在Hash[...]
中。
将其附加到数组以使用以下内容聚合所有创建的哈希值:
user_hashes = []
users.each do |user|
user_hashes << user.split("\n").reject(&:empty?).map{ |l| l.split(':', 2) }.to_h
end
如果没有显示两个用户而不是一个用户的日志示例,我就无法分解用户如何拆分输出,但这应该非常简单。猜测格式:
users = 'Username:arozar
Index:654
AssignedIP:10.254.254.7
PublicIP:4.2.2.2
Protocol:AnyConnect-ParentSSL-TunnelDTLS-Tunnel
License:AnyConnectEssentials
Encryption:AnyConnect-Parent:(1)noneSSL-Tunnel:(1)AES256DTLS-Tunnel:(1)AES256
Hashing:AnyConnect-Parent:(1)noneSSL-Tunnel:(1)SHA1DTLS-Tunnel:(1)SHA1
BytesTx:6104355
BytesRx:1191505
GroupPolicy:vpn
TunnelGroup:anyconnect
LoginTime:08:51:55ESTMonNov32014
Duration:1h:08m:48s
Inactivity:0h:00m:00s
NACResult:Unknown
VLANMapping:N/A
VLAN:none
Username:popeye
Index:655
AssignedIP:10.254.254.8
PublicIP:4.2.2.3
Protocol:AnyConnect-ParentSSL-TunnelDTLS-Tunnel
License:AnyConnectEssentials
Encryption:AnyConnect-Parent:(1)noneSSL-Tunnel:(1)AES256DTLS-Tunnel:(1)AES256
Hashing:AnyConnect-Parent:(1)noneSSL-Tunnel:(1)SHA1DTLS-Tunnel:(1)SHA1
BytesTx:6104355
BytesRx:1191505
GroupPolicy:vpn
TunnelGroup:anyconnect
LoginTime:09:52:56estmonnov32014
Duration:1h:08m:47s
Inactivity:0h:00m:00s
NACResult:Unknown
VLANMapping:N/A
VLAN:none
'
这是将其分解为哈希数组的代码:
user_hashes = []
users.split("\n").reject(&:empty?).slice_before(/^Username/).each do |user|
user_hashes << user.map{ |l| l.split(':', 2) }.to_h
end
user_hashes
看起来像什么:
user_hashes
# => [{"Username"=>"arozar",
# "Index"=>"654",
# "AssignedIP"=>"10.254.254.7",
# "PublicIP"=>"4.2.2.2",
# "Protocol"=>"AnyConnect-ParentSSL-TunnelDTLS-Tunnel",
# "License"=>"AnyConnectEssentials",
# "Encryption"=>
# "AnyConnect-Parent:(1)noneSSL-Tunnel:(1)AES256DTLS-Tunnel:(1)AES256",
# "Hashing"=>
# "AnyConnect-Parent:(1)noneSSL-Tunnel:(1)SHA1DTLS-Tunnel:(1)SHA1",
# "BytesTx"=>"6104355",
# "BytesRx"=>"1191505",
# "GroupPolicy"=>"vpn",
# "TunnelGroup"=>"anyconnect",
# "LoginTime"=>"08:51:55ESTMonNov32014",
# "Duration"=>"1h:08m:48s",
# "Inactivity"=>"0h:00m:00s",
# "NACResult"=>"Unknown",
# "VLANMapping"=>"N/A",
# "VLAN"=>"none"},
# {"Username"=>"popeye",
# "Index"=>"655",
# "AssignedIP"=>"10.254.254.8",
# "PublicIP"=>"4.2.2.3",
# "Protocol"=>"AnyConnect-ParentSSL-TunnelDTLS-Tunnel",
# "License"=>"AnyConnectEssentials",
# "Encryption"=>
# "AnyConnect-Parent:(1)noneSSL-Tunnel:(1)AES256DTLS-Tunnel:(1)AES256",
# "Hashing"=>
# "AnyConnect-Parent:(1)noneSSL-Tunnel:(1)SHA1DTLS-Tunnel:(1)SHA1",
# "BytesTx"=>"6104355",
# "BytesRx"=>"1191505",
# "GroupPolicy"=>"vpn",
# "TunnelGroup"=>"anyconnect",
# "LoginTime"=>"09:52:56estmonnov32014",
# "Duration"=>"1h:08m:47s",
# "Inactivity"=>"0h:00m:00s",
# "NACResult"=>"Unknown",
# "VLANMapping"=>"N/A",
# "VLAN"=>"none"}]
slice_before
是一种很好的方法,它采用一种模式来标记应该开始新子数组的行。
另外,请将此作为示例代码中前三行的替代方法进行冥想:
ac_array = []
`show vpn-sessiondb anyconnect`.split("\n").reject(&:empty?).map{ |l| l.split(':', 2) }.to_h
这仅适用于上面针对单个用户显示的输出。