关于regex:解析字符串:提取单词和短语[JavaScript]

关于regex:解析字符串:提取单词和短语[JavaScript]

parsings strings: extracting words and phrases [JavaScript]

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

例:

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

我想知道是否可以通过单个RegEx而不是执行复杂的解析或拆分和重新合并操作来实现。

任何帮助将不胜感激!


1
2
var str = 'foo bar"lorem ipsum" baz';  
var results = str.match(/("[^"]+"|[^"\s]+)/g);

...返回您要查找的数组。
但是请注意:

  • 包含引号,因此可以在结果上用replace(/^"([^"]+)"$/,"$1")删除。
  • 引号之间的空格将保持不变。因此,如果loremipsum之间存在三个空格,它们将出现在结果中。您可以通过在结果上运行replace(/\s+/,"")来解决此问题。
  • 如果ipsum之后没有结尾的"(即,报价错误的短语),您将得到:['foo', 'bar', 'lorem', 'ipsum', 'baz']

尝试这个:

1
2
3
4
5
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周围没有多余的双引号

尽管它假定输入在正确的位置具有双引号:

1
2
3
4
5
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"]

并且不会处理转义的双引号(这是一个问题吗?):

1
2
3
4
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
2
3
4
5
6
7
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);

作为记录,这是我想出的可憎之处:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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,"
", buffer);
}
items = items.concat(buffer);

//console.log(items);

怎么样,

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

然后传递输出以丢失引号。

交替,

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

然后执行pass n输出以丢失空捕获。


ES6解决方案支持:

  • 除空格外,按空格分隔
  • 删除引号,但不删除反斜杠转义引号
  • 转义报价成为报价

码:

1
2
3
4
5
6
7
8
9
10
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

输出:

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

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

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

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

纯JavaScript示例

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

输出:

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


一个简单易懂的解决方案。适用于所有定界符和" join"字符。还支持长度超过两个单词的"连接"单词。

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

有点像AC的答案,但有点整洁...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
  }

一个简单的正则表达式将起作用,但会保留引号。例如

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

编辑:被shyamsundar殴打,对不起,双重回答


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

尽管包含了边界引号


推荐阅读

    linux命令替换字符串?

    linux命令替换字符串?,字符串,文件,批量,首次,数据,命令,内容,方法,用字,结

    linux命令中转义字符?

    linux命令中转义字符?,标准,本行,密码,字符,电脑,系统,环境,数据,命令,终端,l

    linux命令行字符颜色?

    linux命令行字符颜色?,系统,地址,代码,信息,数字,软件,通用,电脑,颜色,命令,l

    linux命令支持通配符?

    linux命令支持通配符?,工具,系统,命令,灵活,较大,名称,名字,环境,数字,文件,L

    linux中替换字符命令?

    linux中替换字符命令?,工作,地址,系统,命令,资料,数据,信息,商业,管理,目录,L

    linux拼接字符串命令?

    linux拼接字符串命令?,系统,工作,代码,工具,名称,信息,地址,时间,数据,命令,l

    linux图形转字符命令?

    linux图形转字符命令?,系统,电脑,密码,界面,情况,地方,工具,图形界面,字符,

    linux隐藏字符的命令?

    linux隐藏字符的命令?,工作,地址,系统,发行,信息,标准,管理,命令,目录,文件,

    linux命令行最大字符?

    linux命令行最大字符?,系统,工作,数字,地址,等级,设备,软件,信息,标准,设计,l

    添加字符串命令linux?

    添加字符串命令linux?,情况,名称,文件,位置,名字,地方,连续,信息,命令,内容,L

    linux支持管道的命令?

    linux支持管道的命令?,通信,标准,系统,信息,地方,数据,管道,环境,设备,工具,L

    linux命令行大字符?

    linux命令行大字符?,工作,地址,系统,信息,管理,第一,发行,在线,最新,标准,lin

    linux磁盘分割命令?

    linux磁盘分割命令?,系统,工具,环境,设备,电脑,情况,信息,分区,网络,首次,lin

    linux用什么分割命令?

    linux用什么分割命令?,产品,技术,经理,培训,系统,软件,命令,数据,人工智能,

    linux命令查找字符串?

    linux命令查找字符串?,工具,信息,命令,字符串,系统,工作,文件,范本,样式,文

    linux命令字符搜索?

    linux命令字符搜索?,系统,工具,命令,灵活,信息,工作,字符串,文本,文件,模式,l

    linux大写字符命令?

    linux大写字符命令?,系统,工作,信息,档案,数字,地址,命令,名称,密码,时间,lin

    linux字符匹配命令?

    linux字符匹配命令?,工作,地址,管理,系统,工具,标准,命令,目录,信息,文件,Lin

    linux字符替换命令?

    linux字符替换命令?,系统,数据,软件,字符串,文件,命令,实时,首次,位置,工作,l

    linux删除字符的命令?

    linux删除字符的命令?,系统,软件,名称,文件,档案,不了,命令,字符,目录,字母,l