0

我有一个字符串如下:

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

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

我在这个网站上看到了类似的帖子,但不知道在上述情况下如何使用正则表达式。任何想法如何提取上述字符串。

4

2 回答 2

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"]
于 2013-08-14T08:56:29.307 回答
1

由于您不了解正则表达式,因此我们暂时将它们排除在外,并尝试手动解析,这更容易理解。

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

"{\"@Network\":{\"command\":\"Connect\",\"data\":{\"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

现在,我们知道:

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

让我们找到所有这些:

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.

如果布局从不改变并且始终保持不变,那么您的interesting-data 将始终位于第 13 位:

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

现在,只需剥离虚假字符。由于语法是恒定的,因此要从两侧剪切 2 个字符:

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。但是,看:所有其他冒号之前总是有一个引号!

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

现在我们tmp是:

{"@Network"=>{"command"=>"Connect","data"=>{"Id"=>"xx:xx:xx:xx:xx:xx","Name"=>"somename" ,"密码"=>"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 哈希非常相似,因为它显然被格式化为 JSON,它是一个哈希 -也喜欢结构。使用正确的格式读取工具通常是最好的主意,但请注意 JSON 库在被要求读取数据时 - 将读取所有数据,然后您可以询问他们“在关键 xx/yy/zz 里面有什么",就像我向您展示的 read-it-as-a-Hash 尝试一样。有时,当您的程序在截止日期前很短时,您无法通读所有内容。然后,使用正则表达式扫描或手动扫描“已知标记”可能(不是必须)更快,因此更可取。但是,仍然不太方便。

于 2013-08-14T09:31:00.977 回答