Подтвердить что ты не робот

Разделить строку пробелами, сохраняя процитированные сегменты, позволяя избежать кавычек

В настоящее время я использую это регулярное выражение для разделения строк на все пробелы, если только это не указано в сегменте:

keywords = 'pop rock "hard rock"';
keywords = keywords.match(/\w+|"[^"]+"/g);
console.log(keywords); // [pop, rock, "hard rock"]

Однако, я также хочу, чтобы у вас были котировки в ключевых словах, например:

keywords = 'pop rock "hard rock" "\"dream\" pop"';

Это должно возвращать

[pop, rock, "hard rock", "\"dream\" pop"]

Какой самый простой способ достичь этого?

4b9b3361

Ответ 1

Вы можете изменить свое регулярное выражение на:

keywords = keywords.match(/\w+|"(?:\\"|[^"])+"/g);

Вместо [^"]+ у вас есть (?:\\"|[^"])+, который должен быть понятным - разрешить \" или другой символ, но не неэкономную цитату.

Важное замечание состоит в том, что если вы хотите, чтобы строка содержала литеральную косую черту, она должна быть:

keywords = 'pop rock "hard rock" "\\"dream\\" pop"'; //note the escaped slashes.

Кроме того, существует небольшая несогласованность между \w+ и [^"]+ - например, она будет соответствовать слову "ab*d", но не ab*d (без кавычек). Вместо этого используйте [^"\s]+, который будет соответствовать не-пробелам.

Ответ 2

Решение ES6, поддерживающее:

  • Разделить пространство, за исключением внутренних кавычек
  • Удаление котировок, но не для обратных косов с экранированными кавычками
  • Исключенная цитата станет цитатой
  • Может помещать кавычки куда угодно

код:

keywords.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

Вывод:

[ 'pop', 'rock', 'hard rock', '"dream" pop' ]

Ответ 3

Если ответ Kobi хорошо работает для строки примера, это происходит не тогда, когда в кавычках более нескольких последовательных escape-символов (обратных косых черт), когда Tim Pietzcker заметил это в комментариях. Чтобы обрабатывать эти случаи, шаблон можно записать следующим образом (для метода сопоставления):

(?=\S)[^"\s]*(?:"[^\\"]*(?:\\[\s\S][^\\"]*)*"[^"\s]*)*

демо

Где (?=\S) обеспечивает наличие по крайней мере одного символа небелого пробела в текущей позиции, поскольку следующее, описывающее все разрешенные подстроки (включая пробелы между кавычками), является полностью необязательным.

Подробнее:

(?=\S)   # followed by a non-whitespace
[^"\s]*  #"# zero or more characters that aren't a quote or a whitespace
(?: # when a quoted substring occurs:
    "       #"# opening quote
    [^\\"]* #"# zero or more characters that aren't a quote or a backslash
    (?: # when a backslash is encountered:
        \\ [\s\S] # an escaped character (including a quote or a backslash)
        [^\\"]* #"#
    )*
    "         #"# closing quote
    [^"\s]*   #"#
)*

Ответ 4

Я хотел бы указать, что у меня было такое же регулярное выражение, что и вы,

/\w+|"[^"]+"/g

но он не работал с пустой цитируемой строкой, например:

"" "hello" "" "hi"

поэтому мне пришлось изменить квант + на *. это дало мне:

str.match(/\w+|"[^"]*"/g);

Это нормально.

(например: https://regex101.com/r/wm5puK/1)