ruby-on-rails - 如何进行多行匹配并将它们分配给哈希?

标签 ruby-on-rails ruby regex

我正在将 net::ssh session 的输出发送到 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 的未定义方法‘[]’”。

最佳答案

您可以为每个用户执行以下操作。

代码

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,但我更喜欢原样。

关于ruby-on-rails - 如何进行多行匹配并将它们分配给哈希?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26721800/

相关文章:

java - 如何获取空格后面的单词首次出现后的剩余文本?

ruby-on-rails - ExecJS::RuntimeError: SyntaxError: 意外的标记:运算符 (>) (行:22342,列:24,位置:826182)

css - Codekit 和 Zurb Foundation 错误

java - Groovy 编码约定?

c# - 否定空格、正斜杠和反斜杠的正则表达式

regex - 如何检测 Perl 正则表达式中有多少捕获组?

ruby-on-rails - 使用elasticsearch进行索引映射时将索引设置为not_analyzed有什么作用?

ruby-on-rails - 如何在 Rails 3.2 erb 中使用 eval 在运行时执行存储在字符串中的 View 代码?

javascript - ruby rails : Stripe JS & Elements causing Content Security Policy error

ruby - 在没有 Rails 的情况下在 Ruby 中本地化数字