ruby提取两个字符串之间的字符串

时间:2013-08-14 08:26:00

标签: ruby

我的字符串如下:

str1='"{\"@Network\":{\"command\":\"Connect\",\"data\":
{\"Id\":\"xx:xx:xx:xx:xx:xx\",\"Name\":\"somename\",\"Pwd\":\"123456789\"}}}\0"'

我想从上面的字符串中提取 somename 字符串。 xx:xx:xx:xx:xx:xx somename 123456789 的值可以更改,但语法将保持与上述相同。< / p>

我在这个网站上看过类似的帖子,但在上面的例子中不知道如何使用正则表达式。 任何想法如何提取上面的字符串。

2 个答案:

答案 0 :(得分:5)

将字符串解析为JSON并以此方式获取值。

require 'json'
str = "{\"@Network\":{\"command\":\"Connect\",\"data\":{\"Id\":\"xx:xx:xx:xx:xx:xx\",\"Name\":\"somename\",\"Pwd\":\"123456789\"}}}\0"
json = JSON.parse(str.strip)
name = json["@Network"]["data"]["Name"]
pwd = json["@Network"]["data"]["Pwd"]

答案 1 :(得分:1)

由于你不知道正则表达式,让我们暂时不做它们并尝试手动解析,这更容易理解。

您的原始输入,没有外部撇号和变量名称是:

  

“{\” @网络\ “:{\” 命令\ “:\” 连接\ “\ ”数据\“:{\ ”ID \“:\” XX:XX:XX:XX:XX: XX \”,\ “名称\”:\ “somename \”,\ “密码\”:\ “123456789 \”}}} \ 0"

你说你需要获得'somename'值并且'语法不会改变'。凉!。

首先,查看分隔该值:它有引号,然后左边有一个冒号,右边有逗号。但是,查看其他部分,此类布局也会在command附近和pwd附近使用。所以,冒号引用数据引用逗号是不够的。进一步向两侧看,有一个\"Name\"。除了这个地方,输入数据中的任何地方都不会发生。这太棒了!这意味着,只需搜索\"Name\"文字,我们就可以快速找到数据的下落:

inputdata = .....
estposition = inputdata.index('\"Name\"')
raise "well-known marker wa not found in the input" unless estposition

现在,我们知道:

  • 部分开始的地方
  • 并且在“名称”文本之后总是有冒号,引号,然后是有趣的数据
  • 并且在有趣的数据
  • 之后总是有一个引用

让我们找到所有这些:

colonquote = inputdata.index(':\"', estposition)
datastart = colonquote+3
lastquote = inputdata.index('\"', datastart)
dataend = lastquote-1

index会返回匹配的开始位置,因此会返回:的位置和\的位置。由于我们希望在它们之间获取文字,因此我们必须在开始时添加/减去一些位置以移过:\"或在结束时从\"移回。

然后,从它们之间获取数据:

value = inputdata[datastart..dataend]

就是这样。

现在,退一步再次查看输入数据。你说语法总是一样的。各个位显然用冒号和逗号分隔。让我们直接尝试使用它:

parts = inputdata.split(/[:,]/)
=> ["\"{\\\"@Network\\\"",
 "{\\\"command\\\"",
 "\\\"Connect\\\"",
 "\\\"data\\\"",
 "\n{\\\"Id\\\"",
 "\\\"xx",
 "xx",
 "xx",
 "xx",
 "xx",
 "xx\\\"",
 "\\\"Name\\\"",
 "\\\"somename\\\"",
 "\\\"Pwd\\\"",
 "\\\"123456789\\\"}}}\\0\""]

现在请忽略正则表达式。假设它说a colon or comma。现在,在parts中,您将获得通过在inputdata处将colon or comma切成碎片而检测到的所有部分。

如果布局永远不会改变并且始终相同,那么您感兴趣的数据将始终位于第13位:

almostvalue = parts[12]
=> "\\\"somename\\\""

现在,只是删除虚假角色。由于语法是不变的,所以从两边都要切出两个字符:

value = almostvalue[2..-3]

好的,另一种方式。由于正则表达式已经出现,让我们试试吧。我们知道:

  • 数据的前缀为\"Name\",然后是冒号和斜杠引用
  • 数据由一些没有引号的文本组成(好吧,至少我猜是这样)
  • 数据以斜杠引用结束

正则表达式语法中的部分分别为:

  • \ “名称\”:\“
  • [^ \“] *
  • \“

一起:

inputdata =~ /\\"Name\\":\\"([^\"]*)\\"/
value = $1

请注意,我用()包围了有趣的部分,因此在成功匹配后,该部分在$1特殊变量中可用。

另一种方式:

如果仔细查看语法,它实际上类似于一组嵌入式哈希:

\"
{ \"@Network\" :
  { \"command\" : \"Connect\",
    \"data\" :
    { \"Id\" : \"xx:xx:xx:xx:xx:xx\",
      \"Name\" : \"somename\",
      \"Pwd\" : \"123456789\"
    }
  }
}
\0\"

如果我们写一些类似Ruby哈希的东西:

{ "@Network" =>
  { "command" => "Connect",
    "data" =>
    { "Id" => "xx:xx:xx:xx:xx:xx",
      "Name" => "somename",
      "Pwd" => "123456789"
    }
  }
}

有什么区别?冒号被=>替换,并且引号之前的斜线消失了。哦,也开场/关闭\“已经不见了,最后\0也消失了。让我们玩吧:

tmp = inputdata[2..-4]   # remove opening \" and closing \0\"
tmp.gsub!('\"', '"')     # replace every \" with just "

现在,冒号怎么样..我们不能只用:替换=>,因为它会损坏xx:xx:xx:xx:xx:xx部分的内部冒号..但是,看看:所有< strong>其他冒号总是在他们面前引用!

tmp.gsub!('":', '"=>')     # replace every quote-colon with quote-arrow

现在我们的tmp是:

  

{ “@网络”=&GT; { “命令”=&gt; “中连接”, “数据”=&GT; { “ID”=&gt; “中XX:XX:XX:XX:XX:XX”,”名称 “=&gt;” 中somename”, “密码”=&gt; “中123456789”}}}

格式化了一点:

{ "@Network"=>
   { "command"=>"Connect",
     "data"=>
     {  "Id"=>"xx:xx:xx:xx:xx:xx","Name"=>"somename","Pwd"=>"123456789" }
   }
}

所以,它看起来就像一个Ruby哈希。让我们尝试'解析'它:

packeddata = eval(tmp)
value = packeddata['@Network']['data']['Name']

完成。

嗯,这已经有所增长, Jonas 明显更快,所以我将JSON部分留给他,因为他已经写过了;)数据与Ruby hash非常相似,因为它显然格式化为JSON,这也是类似哈希的结构。使用正确的格式阅读工具通常是最好的想法,但请注意,当被要求阅读数据时,JSON库将读取所有数据,然后您可以询问它们“内部有什么内容”关键的xx / yy / zz“,就像我向你展示了一下这样的哈希尝试。有时当你的课程在截止日期前很短时,你就无法全部阅读。然后,使用正则表达式扫描或手动扫描“已知标记”可能(不一定)要快得多,因此更加优先。但是,更不方便。玩得开心。