parsings字符串:提取单词和短语[JavaScript]

parsings字符串:提取单词和短语[JavaScript],javascript,regex,parsing,Javascript,Regex,Parsing,我需要在一个以空格分隔的术语列表中支持精确的短语(用引号括起来)。 因此,用空格字符分割相应的字符串已不再足够 例如: input : 'foo bar "lorem ipsum" baz' output: ['foo', 'bar', 'lorem ipsum', 'baz'] 我想知道这是否可以用单个正则表达式实现,而不是执行复杂的解析或拆分和重新连接操作 任何帮助都将不胜感激 'foo bar "lorem ipsum" baz'.match(/"[^"]*"|\w+/g); 虽然包含

我需要在一个以空格分隔的术语列表中支持精确的短语(用引号括起来)。 因此,用空格字符分割相应的字符串已不再足够

例如:

input : 'foo bar "lorem ipsum" baz'
output: ['foo', 'bar', 'lorem ipsum', 'baz']
我想知道这是否可以用单个正则表达式实现,而不是执行复杂的解析或拆分和重新连接操作

任何帮助都将不胜感激

'foo bar "lorem ipsum" baz'.match(/"[^"]*"|\w+/g);

虽然包含了边界引号,但一个简单的正则表达式只需保留引号即可。e、 g

'foo bar "lorem ipsum" baz'.match(/("[^"]*")|([^\s"]+)/g)
output:   ['foo', 'bar', '"lorem ipsum"', 'baz']
编辑:被shyamsundar打败了,很抱歉双重回答

output = /(".+?"|\w+)/g.exec(input)
然后传递输出以丢失引号

或者

output = /"(.+?)"|(\w+)/g.exec(input)
然后执行passn输出以丢失空捕获

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']结束。
试试这个:

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 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);
var输入='foo bar“lorem ipsum”door sit amet“baz';
var术语=输入。拆分(“”);
var项目=[];
var缓冲区=[];
对于(var i=0;i
一个易于理解且通用的解决方案。适用于所有分隔符和“连接”字符。还支持长度超过两个单词的“连接”单词…例如

“你好,我的名字是‘乔恩·特拉华·史密斯·弗雷德’,我有一个‘长名字’”

有点像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;
  }

这可能是一个很晚的回答,但我有兴趣回答

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

纯javascript示例

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

["The", "rain", "in", ""SPAIN stays"", "mainly", "in", "the", "plain"]

ES6解决方案支持:

  • 除内引号外按空格拆分
  • 删除引号但不删除反斜杠转义引号
  • 转义引号变为引号
代码:

输出:

[ 'foo', 'bar', 'lorem ipsum', 'baz' ]

在公认答案的基础上,这里有一个搜索引擎解析器

  • 可以匹配短语或单词
  • 将短语视为正则表达式
  • 在多个属性(例如item.title和item.body)之间执行布尔或布尔运算
  • 处理前缀为的单词或短语的否定-
将短语视为正则表达式可以使UI更简单

const matchOrIncludes=(str,search,useMatch=true)=>{
如果(使用匹配){
让结果=假
试一试{
结果=str.match(搜索)
}捕捉(错误){
返回错误
}
返回结果
}
返回str.includes(搜索)
}
常量itemMatches=(项目、搜索字符串、字段)=>{
const keywords=searchString.toString().replace(/\s\s+/g',).trim().toLocaleLowerCase().match(/(?[^”]+“|[^”\s]+)/g)| |[]
for(设i=0;iconsole.log(itemMatches(item,'text',['title','body'])
唯一的问题是所有引号都被删除了,即引号字符本身不可搜索。很好,只是找不到scape引号,比如:['foo','bar','lorem\'ipsum','baz']很好!这是一种实现搜索引擎解析器的简单方法,用于搜索短语和单个单词。。。非常感谢!谢谢你的回答。我发布了一个搜索引擎解析器的实现,用于短语和单个单词,作为另一个答案,其中短语被视为正则表达式。这不是unicode友好的,例如,它不支持阿拉伯语字符。
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' ]