разбор строк: извлечение слов и фраз [JavaScript] - PullRequest
9 голосов
/ 15 сентября 2008

Мне нужно поддерживать точные фразы (заключенные в кавычки) в список терминов, разделенных пробелами. Таким образом, разделения соответствующей строки пробелом больше не достаточно.

Пример:

input : 'foo bar "lorem ipsum" baz'
output: ['foo', 'bar', 'lorem ipsum', 'baz']

Интересно, можно ли этого достичь с помощью одного RegEx, вместо выполнения сложных операций синтаксического анализа или разделения и повторного объединения.

Любая помощь будет принята с благодарностью!

Ответы [ 10 ]

15 голосов
/ 15 сентября 2008
var str = 'foo bar "lorem ipsum" baz';  
var results = str.match(/("[^"]+"|[^"\s]+)/g);

... возвращает искомый массив.
Обратите внимание, однако:

  • Ограничивающие кавычки включены, поэтому могут быть удалены с replace(/^"([^"]+)"$/,"$1") по результатам.
  • Пробелы между кавычками останутся нетронутыми. Итак, если между lorem и ipsum есть три пробела, они будут в результате. Вы можете исправить это, запустив replace(/\s+/," ") для результатов.
  • Если после ipsum нет закрывающего " (то есть неправильно цитируемой фразы), вы получите: ['foo', 'bar', 'lorem', 'ipsum', 'baz']
3 голосов
/ 15 сентября 2008

Попробуйте это:

var input = 'foo bar "lorem ipsum" baz';
var R =  /(\w|\s)*\w(?=")|\w+/g;
var output = input.match(R);

output is ["foo", "bar", "lorem ipsum", "baz"]

Обратите внимание, что вокруг lorem ipsum нет лишних двойных кавычек

Хотя предполагается, что ввод содержит двойные кавычки в правильном месте:

var input2 = 'foo bar lorem ipsum" baz'; var output2 = input2.match(R);
var input3 = 'foo bar "lorem ipsum baz'; var output3 = input3.match(R);

output2 is ["foo bar lorem ipsum", "baz"]
output3 is ["foo", "bar", "lorem", "ipsum", "baz"]

И не обработает экранированные двойные кавычки (это проблема?):

var input4 = 'foo b\"ar  bar\" \"bar "lorem ipsum" baz';
var output4 = input4.match(R);

output4 is  ["foo b", "ar bar", "bar", "lorem ipsum", "baz"]
1 голос
/ 15 сентября 2008

Большое спасибо за быстрые ответы!

Вот краткое изложение вариантов для потомков:

var input = 'foo bar "lorem ipsum" baz';

output = input.match(/("[^"]+"|[^"\s]+)/g);
output = input.match(/"[^"]*"|\w+/g);
output = input.match(/("[^"]*")|([^\s"]+)/g)
output = /(".+?"|\w+)/g.exec(input);
output = /"(.+?)"|(\w+)/g.exec(input);

Для справки, вот мерзость, которую я придумал:

var input = 'foo bar "lorem ipsum" "dolor sit amet" baz';
var terms = input.split(" ");

var items = [];
var buffer = [];
for(var i = 0; i < terms.length; i++) {
    if(terms[i].indexOf('"') != -1) { // outer phrase fragment -- N.B.: assumes quote is either first or last character
        if(buffer.length === 0) { // beginning of phrase
            //console.log("start:", terms[i]);
            buffer.push(terms[i].substr(1));
        } else { // end of phrase
            //console.log("end:", terms[i]);
            buffer.push(terms[i].substr(0, terms[i].length - 1));
            items.push(buffer.join(" "));
            buffer = [];
        }
    } else if(buffer.length != 0) { // inner phrase fragment
        //console.log("cont'd:", terms[i]);
        buffer.push(terms[i]);
    } else { // individual term
        //console.log("standalone:", terms[i]);
        items.push(terms[i]);
    }
    //console.log(items, "\n", buffer);
}
items = items.concat(buffer);

//console.log(items);
1 голос
/ 15 сентября 2008

как насчет

output = /(".+?"|\w+)/g.exec(input)

затем сделайте проход на выходе, чтобы потерять кавычки.

поочередно,

output = /"(.+?)"|(\w+)/g.exec(input)

затем выполните pass n output, чтобы потерять пустые записи.

0 голосов
/ 26 октября 2017

ES6 решение с поддержкой:

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

Код:

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

Выход:

[ 'foo', 'bar', 'lorem ipsum', 'baz' ]
0 голосов
/ 29 октября 2014

Это может быть очень поздний ответ, но мне интересно ответить

([\w]+|\"[\w\s]+\")

http://regex101.com/r/dZ1vT6/72

Пример чистого JavaScript

 'The rain in "SPAIN stays" mainly in the plain'.match(/[\w]+|\"[\w\s]+\"/g)

Выходы:

["The", "rain", "in", ""SPAIN stays"", "mainly", "in", "the", "plain"]
0 голосов
/ 05 июня 2013

Тот, который легко понять, и общее решение. Работает для всех разделителей и символов «соединения». Также поддерживает «объединенные» слова длиной более двух слов .... т.е. списки типа

"hello my name is 'jon delaware smith fred' I have a 'long name'" ....

Немного похоже на ответ AC, но немного аккуратнее ...

function split(input, delimiter, joiner){
    var output = [];
    var joint = [];
    input.split(delimiter).forEach(function(element){
        if (joint.length > 0 && element.indexOf(joiner) === element.length - 1)
        {
            output.push(joint.join(delimiter) + delimiter + element);
            joint = [];
        }
        if (joint.length > 0 || element.indexOf(joiner) === 0)
        {
            joint.push(element);
        }
        if (joint.length === 0 && element.indexOf(joiner) !== element.length - 1)
        {
            output.push(element);
            joint = [];
        }
    });
    return output;
  }
0 голосов
/ 15 сентября 2008

Если вам просто интересно, как создать регулярное выражение, вы можете попробовать Expresso ( Expresso link ). Это отличный инструмент, чтобы научиться создавать регулярные выражения, чтобы вы знали, что означает синтаксис.

Когда вы построите свое собственное выражение, вы можете выполнить .match для него.

0 голосов
/ 15 сентября 2008

Простое регулярное выражение сделает, но оставит кавычки. например,

'foo bar "lorem ipsum" baz'.match(/("[^"]*")|([^\s"]+)/g)
output:   ['foo', 'bar', '"lorem ipsum"', 'baz']

редактировать: побежден Шьямсундаром, извините за двойной ответ

0 голосов
/ 15 сентября 2008
'foo bar "lorem ipsum" baz'.match(/"[^"]*"|\w+/g);

ограничивающие кавычки включаются, хотя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...