regex JavaScript按空格分割字符串,但忽略引号中的空格(注意不要也用冒号分割)

qv7cva1a  于 12个月前  发布在  Java
关注(0)|答案(4)|浏览(123)

我需要帮助在JavaScript中通过空格(““)分割字符串,忽略引号表达式中的空格。
我有这个字符串:

var str = 'Time:"Last 7 Days" Time:"Last 30 Days"';

字符串
我希望我的字符串被拆分为2:

['Time:"Last 7 Days"', 'Time:"Last 30 Days"']


但我的代码拆分为4:

['Time:', '"Last 7 Days"', 'Time:', '"Last 30 Days"']


这是我的代码:

str.match(/(".*?"|[^"\s]+)(?=\s*|\s*$)/g);


谢谢你,谢谢

vuv7lop3

vuv7lop31#

s = 'Time:"Last 7 Days" Time:"Last 30 Days"'
s.match(/(?:[^\s"]+|"[^"]*")+/g) 

// -> ['Time:"Last 7 Days"', 'Time:"Last 30 Days"']

字符串
解释:

(?:         # non-capturing group
  [^\s"]+   # anything that's not a space or a double-quote
  |         #   or…
  "         # opening double-quote
    [^"]*   # …followed by zero or more chacacters that are not a double-quote
  "         # …closing double-quote
)+          # each match is one or more of the things described in the group


事实证明,要修复原始表达式,您只需在组上添加+

str.match(/(".*?"|[^"\s]+)+(?=\s*|\s*$)/g)
#                         ^ here.

envsm3lx

envsm3lx2#

ES6解决方案支持:

  • 除内部引号外,按空格分隔
  • 删除引号,但不删除反斜杠转义引号
  • 转义的引用变为引用

代码:

str.match(/\\?.|^$/g).reduce((p, c) => {
        if(c === '"'){
            p.quote ^= 1;
        }else if(!p.quote && c === ' '){
            p.a.push('');
        }else{
            p.a[p.a.length-1] += c.replace(/\\(.)/,"$1");
        }
        return  p;
    }, {a: ['']}).a

字符串
输出量:

[ 'Time:Last 7 Days', 'Time:Last 30 Days' ]

bis0qfac

bis0qfac3#

这对我来说很有用。
var myString = 'foo bar“sdkgyu sdkjbh zkdumps”baz“qux quux”skduy“zsk”'; console.log(myString.split(/([^\s”]+|“[^"]*”)+/g));

**输出:**Array ["",“foo”,““,“bar”,““,““sdkgyu sdkjbh zkdumps”",““,“baz”,““,““qux quux”",““,“skduy”,““,““zsk”“,“"]

4urapxun

4urapxun4#

我知道这个问题是关于正则表达式的,但是你用正则表达式做的字符串分割或子字符串提取等任务越多,你就越会注意到正则表达式的复杂性比字符串的复杂性增长得快得多:首先,你必须避免使用带引号的正则表达式分割,你只需要使用一些几乎随机的正则表达式就可以了;然后你需要尊重双引号区域,你修改你的正则表达式,使它增长3-4倍;等等。最终你的正则表达式变成了一个wunschpunsch,没有清醒的人会想要支持它。所以,虽然正则表达式的解决方案一开始看起来很忍者和elegant,我终于停止使用它,并切换到自定义功能,尊重报价区:

interface IZoneToken {
  begin: string;
  end: string;
}

const ZONE_TOKENS: { [key: string]: IZoneToken } = {
  SINGLE_QUOTES: { begin: '\'', end: '\'' },
  DOUBLE_QUOTES: { begin: '\"', end: '\"' },
  ROUND_BRACKETS: { begin: '(' , end: ')' }
};

function splitRespectingZones(input: string, delimiter: string, zone_tokens: IZoneToken[]): string[] {
  let current_substring = '',
    current_zone_token;
  const substrings = [],
    current_zone_tokens = [];

  for (let i = 0; i < input.length; i++) {
    const symbol = input[i];

    if (symbol === delimiter && !current_zone_tokens.length) {
      substrings.push(current_substring);
      current_substring = '';
    } else {
      if (current_zone_token = zone_tokens.find(x => symbol === x.begin || symbol === x.end)) {
        if (current_zone_token === current_zone_tokens.last()) {
          if (current_zone_token.end === symbol) {
            current_zone_tokens.pop()
          } else {
            current_zone_tokens.push(current_zone_token)
          }
        } else {
          current_zone_tokens.push(current_zone_token)
        }
        current_zone_token = undefined;
      }
      current_substring += symbol;
    }
  }
  if (current_substring) {
    substrings.push(current_substring)
  }
  return substrings;
}

字符串
正如你所看到的,你可以使用任意数量的自定义区域标记,无论是双引号,花括号还是其他一些括号:

splitRespectingZones(`some 'ran dom' "str ings" (fo r) ("example")`, ' ', [
  { begin: '\'', end: '\'' },
  { begin: '\"', end: '\"' },
  { begin: '(' , end: ')' }
])

// ['some', "'ran dom'", '"str ings"', '(fo r)', '("example")']


这是冗长的,但如果您需要修改这个函数,您会喜欢它的逻辑是多么简单
问题中的案例示例:

splitRespectingZones('Time:"Last 7 Days" Time:"Last 30 Days"', ' ', [ { begin: '\"', end: '\"' } ])
// ['Time:"Last 7 Days"', 'Time:"Last 30 Days"']

相关问题