如何将每个引用句子放入数组中(Javascript)

3

我有一个看起来像这样的字符串:

var message = '"this is a question" "answer one" "answer two" "answer three"';

我希望将字符串中引号内的每个句子放入以下形式的数组中:
array = ["this is a question", "answer one", "answer two", "answer three"];

我该如何用JavaScript实现这个?谢谢。


3个回答

3

你尝试过使用 str.split() 吗?

const array = message.split(/\s(?=")/);
//This regex searches for a space, but makes sure it has a " after it.

文档: https://www.w3schools.com/jsref/jsref_split.asp

万一您想要分解正则表达式:

/ start of regex
  \s escaped character: whitespace
  (?= start of positive lookahead
    " literal character: quotation mark
  ) end of positive lookahead
/ end of regex

编辑: Oskar Grosser在评论中说,有时这种方法不起作用。 以下是解决方法:

/(?<=[^\\]?")\s+(?=")/

内容分解:

/ start of regex
  (?<= start of positive lookbehind
    [^ start of negated charset (in case there was any \"s)
      \\ escaped literal character: backslash (\)
    ] end of negated charset
    ? quantifier: 0 or 1 (in case it was at the beginning)
    " literal character: quotation mark (")
  ) end of positive lookbehind
  \s escaped character: whitespace
  + quantifier: 1 or more (for in case there was 2 whitespace instead of 1)
  (?= start of positive lookahead
    " literal character: quotation mark (")
  ) end of positive lookahead
/ end of regex

注意:回顾先行断言在某些浏览器上可以正常工作,但并非所有浏览器都支持。


1
当引号包含尾随空格时并且后面跟着另一个引号(例如 '"Trailing " "Regular"'),此方法将无法按预期工作。当引号之间以一个以上的空格分隔时(例如 '"Two" "white-spaces inbetween"'),此方法也无法按预期工作。 - Oskar Grosser
为了更好地分解正则表达式,请将其复制到此处https://regexr.com/ - Azure

2

试试这个我刚刚编写的函数:

let string = '"this is a question" "answer one" "answer two" "answer three"'
        let string2 = '"this is a question " " answer one" " answer two" "answer three"'
        let string3 = '"this is a question"random omitted "answer one" text between quotes "answer two" zzz "answer three"'
        
        function splitString(string) {
               let wordArray = []
               let incompleteWord = ""
               let quotePos = 0;
               for(let i = 0; i < string.length; i++) {
                 if(string.charAt(i) === '"'){
                   if(quotePos === 0)
                     quotePos = 1
                   else {
                     wordArray.push(incompleteWord.trim())
                     incompleteWord = ""
                     quotePos = 0
                     continue
                   }
                 } else {
                   if(quotePos === 1)
                    incompleteWord += string.charAt(i)
                 }
               }
               return wordArray
             }
    console.log(splitString(string))
    console.log(splitString(string2))
    console.log(splitString(string3))


1
我在Java中做了非常相似的事情,但我很难让我的版本在JS中工作。这个版本可以用,谢谢! - btror
1
它确实有一个问题:引号之间的字符也被添加到 incompleteWord 中。在将它们添加到 incompleteWord 之前检查这些字符是否是引号的一部分应该可以解决这个问题。不过,这是一个很好的解决方案! - Oskar Grosser
非常感谢您指出@OskarGrosser,我简直不敢相信我没有注意到它。我还注意到我的代码没有修剪引号之间的字符,所以我更新了我的代码。再次感谢 :) - Eric McWinNEr

1
  1. 获取完整的引用。可以使用 String.split() 方法来完成。
  2. (可选) 去掉引用中的 "" (双引号)。可以在 Array.map() 中使用 String.replace() 方法来完成。

1. 获取引用

使用以下 正则表达式 将字符串按照 "" (双引号) 之间的空格分割,但不会考虑到转义的双引号 \"/(?<=[^\\]")\s+(?=")/

以下是它的解释:

(?<=[^\\]") # Is preceded by not a backslash and a double quote
            # Better said: is preceded by an un-escaped double quote
\s+         # Consists of at least one, and only white-spaces
(?=")       # Is followed by double quote

如果没有任何字符或者有除了空格以外的字符,就不会进行分割。这样可以允许双引号包含前导或尾随空格(例如" This "),但不能仅由空格组成的双引号。

var message = '"Containing \" escaped quote" "Trailing white-spaces here  " " Beginning and trailing white-spaces here " "  Beginning white-spaces here"';

console.log(message.split(/(?<=[^\\]")\s+(?=")/));

为什么要两边检查?仅向前查看不就足够了吗?

当输入字符串具有带引号部分并在另一个带引号部分之前有尾随空格时,这将成为一个问题,例如"Trailing " "Regular"
在这种情况下,第一次拆分将在"Trailing之后进行,拆分掉其"(双引号)之前的 (空格)。下一个拆分将在第三个"(双引号)处进行,拆分掉它的 (空格)。但是,"Trailing "的结束双引号"现在将成为返回数组的一部分,因为它的两侧都是拆分点。

此外,如果不检查第一个引号是否被转义,则无法使用转义引号。

向前和向后查看都可以解决这个问题。但是,它仍然无法解决" "(包含空格的双引号)被排除的问题。据我所知,使用正则表达式拆分输入字符串以包括这样的“空”双引号是不可能的。

Here is a demonstration of only looking ahead:

var message = '"Containing \" escaped quote" "Trailing white-spaces here  " " Beginning and trailing white-spaces here " "  Beginning white-spaces here"';

console.log(message.split(/\s+(?=")/));

2. 去除嵌套引号

在获取引用字符串后,我们可以使用Array.map()中的String.replace()来删除起始和结束的""(双引号)。

不需要去除转义反斜杠\"(转义的双引号),因为它被解析为"(双引号)。然而,我们的分割正则表达式特别排除了转义的双引号,如前所述。

var message = '"Containing \" escaped quote" "Trailing white-spaces here  " " Beginning and trailing white-spaces here " "  Beginning white-spaces here"';

for (var i of message.split(/(?<=[^\\]")\s+(?=")/).map(i => i.replace(/^"|"$/g, '')))
  console.log(i);

请注意,使用带有 g(全局)标志的正则表达式的 String.replace()String.replaceAll() 相同。但是,我们需要一个正则表达式仅查找开头和尾随引号。

在正则表达式中使用lookbehind时,需要包含[^\]。否则,像“我逃脱了\”“这样的字符串将无法工作。 - Azure
@EarlyBird 然后将末尾的 \\(反斜杠)替换为未引用字符串的结果?我会立即处理。 - Oskar Grosser
刚刚想起来,替换转义引号的反斜杠是不必要的,因为它是一个转义引号,因此会被解析为普通引号。 - Oskar Grosser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接