解析密钥:具有正则表达式的值对

时间:2016-03-21 20:51:00

标签: java regex

我有一个服务,我点击以下面的格式key: value给出回复,我想从中提取键/值对并将其加载到地图中。

state: UP flag: 9 time: 02:29:09.111782 highest_id: num_users: 0 num_records: 0

所以我使用正则表达式解析它并从中提取键/值对。

private static final Pattern PATTERN = Pattern.compile("\\s*(\\S+)\\s*:\\s*(\\S+)");

String response = restTemplate.getForObject(url, String.class);
Matcher m = PATTERN.matcher(response);
while (m.find()) {
    String key = m.group(1).trim();
    String value = m.group(2).trim();
    // load key/value in a map
}

现在上述正则表达式的问题是上述数据 - 它需要highest_id作为键,但它需要num_users: 0,因为它的值是错误的。在这种情况下,它应该以{{1​​}}作为键,值应为空字符串或null,因为该键的highest_id之后没有任何内容,下一个键应为:,值应为{{ 1}}。

我的正则表达式出了什么问题?

5 个答案:

答案 0 :(得分:1)

你可以尝试使用单词边界和负向前瞻的正则表达式:

(\w+):\s(\S*\b(?!:))

在Java中:

Pattern p = Pattern.compile("(\\w+):\\s(\\S*\\b(?!:))");

\b(字边界)和否定前瞻(?!:)是为了确保您不会将下一个字符匹配为当前键的值为空。

RegEx Demo

答案 1 :(得分:1)

这个正则表达式应该匹配整个字符串而没有间隙。如果有间隙出错了(您可以将组(0)的长度相加并将其与字符串长度进行比较)。如果有第二组,则需要进行修剪。 Regex 101

Pattern.compile("([a-z_]+): +([0-9A-Za-z.:]*[0-9A-Za-z.](?: +|$))?");

答案 2 :(得分:0)

您可以使用下一个键或字符串结尾的前瞻。

示例:

String response = "state: UP flag: 9 time: 02:29:09.111782 highest_id: num_users: 0 num_records: 0";
Pattern p = Pattern.compile("([a-z_]+:)(.*?)(?=[a-z_]+:|$)");
Matcher m = p.matcher(response);
while (m.find()) {
    System.out.println(m.group(1) + " -> " + m.group(2));
}

输出:

state: ->  UP 
flag: ->  9 
time: ->  02:29:09.111782 
highest_id: ->  
num_users: ->  0 
num_records: ->  0

故障:

  • ([a-z_]+:)当前密钥
  • (.*?)价值,可以是空的,非贪婪的
  • (?=[a-z_]+:|$)预测下一个键或行尾

当然,如果值看起来像“关键”那么这可能会破坏......

答案 3 :(得分:0)

您可以使用以下正则表达式:

input {
  float: left;
}

.floated-label {
  float: right;
}

.rules {
 overflow: hidden;
}

<div class='rules'>
  <input type="checkbox" />
  <label class="floated-label">Data:</label>
</div>

它使用负向前瞻using Foundation; using System; using System.CodeDom.Compiler; using UIKit; using RedLasterPrototype; using System.Threading.Tasks; using CoreGraphics; using ZXing.Mobile; using ScanditSDK; namespace Prototype { partial class ScanViewController : UIViewController { public static ProductElement ScannedProduct { get; set; } ScanditDelegate scanditDelegate; public static string appKey = "xxxxx"; public ScanViewController(IntPtr handle) : base (handle) { } public async override void ViewDidLoad() { var picker = new ScanditSDK.SIBarcodePicker (appKey); scanditDelegate = new ScanditDelegate (); picker.OverlayController.Delegate = scanditDelegate; PresentViewController (picker, true, null); picker.StartScanning (); } public static ProductElement GetScannedData(string upc) { var _service = new RestService (); var data = _service.GetDataFromUpc (upc); if (data != null) { return data; } return null; } public override void PrepareForSegue (UIStoryboardSegue segue, NSObject sender) { base.PrepareForSegue (segue, sender); if (segue.Identifier == "SegueToProductPage") { var destination = (ScannedProductViewController)segue.DestinationViewController; destination.product = ScannedProduct; } } public class ScanditDelegate : SIOverlayControllerDelegate { public override void DidScanBarcode (SIOverlayController overlayController, NSDictionary barcode) { // perform actions after a barcode was scanned Console.WriteLine ("barcode scanned: {0}, '{1}'", barcode["symbology"], barcode["barcode"]); var code = barcode ["barcode"].ToString(); if(code != null) { ScannedProduct = GetScannedData (code); var x = new ScanViewController (this.Handle); x.PerformSegue ("SegueToProductPage", this); } } public override void DidCancel (SIOverlayController overlayController, NSDictionary status) { // perform actions after cancel was pressed } public override void DidManualSearch (SIOverlayController overlayController, string text) { // perform actions after search was used } } } } 来匹配之前定义的正则表达式,而后面没有冒号“:”字符。

(\s*(\S+)\s*:)(\s*\w*(\s+|$))(?!(:)) 匹配密钥

?!(:)匹配值,后跟空格或行尾

(\s*(\S+)\s*:)仅匹配之前定义的正则表达式时,它不会直接跟冒号字符。

例如,您可以使用此网站:http://www.regexplanet.com/advanced/java/index.html来验证字符串的哪个部分属于哪个组。

使用正则表达式的另一种方法是用空格分割字符串,然后遍历结果数组,如:不均匀索引是键,甚至索引是值[“key1”,“value1”,“key2”,“value2”当然,这只适用于您的键或值本身不包含空格的情况。但是,正则表达式可能也不会起作用。

答案 4 :(得分:0)

使用此正则表达式获取每对:

(\S+):\s(\S*)(?:\b(?!:)|$)

它搜索一个键,然后是一个冒号和一个空格,如果它们不以冒号结尾或者它是行的末尾,则搜索零个或多个字符。

Regex101 Tested

像这样使用:

Map<String, String> pairs = new HashMap<>();
Matcher m = Pattern.compile("(\\S+):\\s(\\S*)(?:\\b(?!:)|$)").matcher(inputText);
while (m.find()) {
    pairs.put(m.group(1), m.group(2));
}

如果缺少一个值,它将放置一个空字符串。

Ideone Tested