使用正则表达式抓取类对象字符串(类似于 JSON)的键/值对

问题描述 投票:0回答:2

对于像

{float: 'null', another: 'foo'}
这样的字符串,我想获取每组键/值对,以便各组输出
float
null
another
foo
。 我当前的正则表达式是
/\{(?<set>(?<key>\w*)\s*\:\s*(?<value>.*)?\s?)*\}/g
它正确地获取键,但是从逗号开始的任何内容都会将其作为值接收。我使用命名组主要是为了清楚起见。无法弄清楚如何提取每个键/值对,特别是当有多个键/值对时。 感谢您的帮助

目前正在尝试

/\{(?<set>(?<key>\w*)\s*\:\s*(?<value>.*)?\s?)*\}/g
,但输出是:

组“设置”:

float: 'null', another: 'foo'
(正确)

组“关键”:

float
(正确)

组“值”:

'null', another: 'foo'
(不正确,我只想
null

如果可能的话希望它捕获所有键/值对


编辑以获得更清晰的信息:

我的具体用例是解析 Markdown 并将其插入 Svelte 中的自定义组件,我想控制从图像上的 Markdown 语法收集道具的能力。根据我在网上收集的有关在图像上添加属性的信息,它应该看起来像这样:

![Alt Text]https://<fullurl>.jpg "This is hover text"){prop1: 'foo', prop2: 'bar', float: true}

正则表达式的原因是解析 Markdown 字符串。它不是 JSON,并且通过遵循 JSON 语义我并没有真正获得任何东西(

"
在关键上)

javascript regex regex-group
2个回答
0
投票

尝试一下这个长的 JavaScript 正则表达式:

/(?<key>\w*)\s*\:\s*(?<value>(?<quote>["'])(?:(?=(?<backslash>\\?))\k<backslash>.)*?\k<quote>|(?<number>[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)|(?<constant>true|false|null))/g

实际操作(整页查看,如果不是,则不全部可见):

const regexKeyValue = /(?<key>\w*)\s*\:\s*(?<value>(?<quote>["'])(?:(?=(?<backslash>\\?))\k<backslash>.)*?\k<quote>|(?<number>[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)|(?<constant>true|false|null))/g;

document.getElementById('search').addEventListener('click', function () {
  const input = document.getElementById('input').value;

  let match,
      i = 1,
      output = [];

  while ((match = regexKeyValue.exec(input)) !== null) {
    console.log(`Match n°${i} : ` + match[0]);
    console.log('match.groups =', match.groups);

    // If the value is starting with quotes, then unquoted it and
    // also replace all the escape sequences (ex: "\\n" should become "\n").
    let value = match.groups.value;
    // If it's double quotes, let's use JSON.parse() as it will handle everything.
    if (value.match(/^"/)) {
      value = JSON.parse(value);
    }
    // If it's simple quotes, we can't use JSON.parse() so we have to trick it a bit.
    else if (value.match(/^'/)) {
      // 1) Remove the simple quotes around.
      // 2) Replace all \' by '.
      // 3) Escape all double quotes (" becomes \").
      // We have to search for all backslashes to handle also an escaped backslash.
      value = value
        .replace(/^'|'$/g, '')
        .replace(/\\(.)/g, function (fullMatch, afterBackslash) {
          if (afterBackslash === "'") {
            return "'";
          } else {
            return fullMatch;
          }
        }).
        replace(/"/g, '\\"');
      console.log(`"${value}"`);
      // Now use JSON.parse();
      value = JSON.parse(`"${value}"`);
    }
    
    // If it's a number or a constant, then convert the string to this real JS value.
    if (typeof match.groups.number !== 'undefined' ||
        typeof match.groups.constant !== 'undefined') {
      value = eval(match.groups.value);
    }

    output.push(
      `Match n°${i++} :\n` +
      `  Key   : ${match.groups.key}\n` +
      `  Value : ${value}\n`
    );
  }

  document.getElementById('output').innerText = output.join("\n");
  document.getElementById('label').classList.remove('hidden');
});
textarea {
  box-sizing: border-box;
  width: 100%;
}

pre {
  overflow-y: scroll;
}

.hidden {
  display: none;
}
<textarea id="input" rows="10">{
  float: 'null',
  another: "foo",
  age: 45,
  type: '"simple" \' quote',
  comment: "Hello,\nA backslash \\, a tab \t and a \"dummy\" word.\nOk?",
  important: true,
  weight: 69.7,
  negative: -2.5
}</textarea>

<button id="search">Search for key-value pairs</button>

<p id="label" class="hidden">Matches:</p>
<pre><code id="output"></code></pre>

相同的正则表达式,带有注释,带有

x
标志 PCRE 提供:

/
(?<key>\w*)
\s*\:\s*
(?<value>
  # A string value, single or double-quoted:
  (?<quote>["'])
    (?:(?=(?<backslash>\\?))\k<backslash>.)*?
  \k<quote>
|
  # Int and float numbers:
  (?<number>[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)
|
  # true, false and null (or other constants):
  (?<constant>true | false | null)
)
/gx

或者更好的是,在 regex101 上,您将获得颜色和解释 右栏:https://regex101.com/r/bBPvUd/1


0
投票

正如评论中提到的,

eval()
被认为是“邪恶的”或至少是不安全的。我已经忘记了具体原因,与跨端脚本有关。但是,如果在“安全”环境中使用,即。 e.对于您可以完全控制的输入的预处理,那么它可能仍然是可以接受的。

const md=`Some text and now the image: 
![Alt Text]https://<fullurl>.jpg "This is hover text"){prop1: 'foo', prop2: 'bar', float: true} 
and some more text.

A new paragraph any yet nother picture
![Alt Text2]https://<fullerURL>.jpg "This is another hover text"){prop1: 'fool', prop2: 'bart', float: false} and this is the end.`;

function unsafeParse(s){
 return s.match(/\{[^}]+\}/g).map(t=>eval(`(${t})`));
}

// ouputs an array of all image property objects:
console.log(unsafeParse(md));

上述内容并不完全安全,因为包含“}”字符的属性值会导致问题......

© www.soinside.com 2019 - 2024. All rights reserved.