我有一个服务,我点击以下面的格式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}}。
我的正则表达式出了什么问题?
答案 0 :(得分:1)
你可以尝试使用单词边界和负向前瞻的正则表达式:
(\w+):\s(\S*\b(?!:))
在Java中:
Pattern p = Pattern.compile("(\\w+):\\s(\\S*\\b(?!:))");
\b
(字边界)和否定前瞻(?!:)
是为了确保您不会将下一个字符匹配为当前键的值为空。
答案 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(?!:)|$)
它搜索一个键,然后是一个冒号和一个空格,如果它们不以冒号结尾或者它是行的末尾,则搜索零个或多个字符。
像这样使用:
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));
}
如果缺少一个值,它将放置一个空字符串。