9

それ以外の場合はスペースで区切られた用語のリストで、正確なフレーズ (引用符で囲まれている) をサポートする必要があります。したがって、それぞれの文字列をスペース文字で分割するだけでは不十分です。

例:

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

複雑な解析や分割と再結合の操作を実行するのではなく、単一の RegEx でこれを達成できるかどうか疑問に思います。

どんな助けでも大歓迎です!

4

10 に答える 10

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

...探している配列を返します。
ただし、次の点に注意してください。

  • 境界引用符が含まれているため、結果から削除できますreplace(/^"([^"]+)"$/,"$1")
  • 引用符の間のスペースはそのまま残ります。したがって、との間に3つのスペースがある場合loremipsumそれらは結果に含まれます。結果を実行することでこれを修正できますreplace(/\s+/," ")
  • "後に終了がない場合ipsum(つまり、誤って引用されたフレーズ)、次のようになります。['foo', 'bar', 'lorem', 'ipsum', 'baz']
于 2008-09-15T17:59:11.137 に答える
3

これを試して:

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"]
于 2008-09-15T18:16:42.123 に答える
2

迅速な対応に感謝します。

後世のために、オプションの概要を次に示します。

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);
于 2008-09-15T18:45:23.990 に答える
2

単純な正規表現で十分ですが、引用符は残しておいてください。例えば

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

編集:シャムスンダルに殴られました、二重の答えでごめんなさい

于 2008-09-15T17:49:19.227 に答える
1
'foo bar "lorem ipsum" baz'.match(/"[^"]*"|\w+/g);

ただし、境界引用符は含まれます

于 2008-09-15T17:43:48.910 に答える
1

どうですか、

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

次に、引用符を失うために出力を渡します。

交互に、

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

次に、パス n 出力を実行して、空のキャプチャを失います。

于 2008-09-15T17:50:11.190 に答える
0

これは非常に遅い答えかもしれませんが、答えることに興味があります

([\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"]
于 2014-10-29T09:31:20.500 に答える
0

受け入れられた回答を拡張すると、検索エンジンパーサーが次のようになります。

  • フレーズまたは単語に一致することができます
  • フレーズを正規表現として扱います
  • 複数のプロパティ (item.title と item.body など) の間でブール OR を実行します。
  • - が前に付いている場合、単語または句の否定を処理します。

フレーズを正規表現として扱うことで、私の目的のために UI がよりシンプルになります。

const matchOrIncludes = (str, search, useMatch = true) => {
  if (useMatch) {
    let result = false
    try {
      result = str.match(search)
    } catch (err) {
      return false
    }
    return result
  }
  return str.includes(search)
}


const itemMatches = (item, searchString, fields) => {
  const keywords = searchString.toString().replace(/\s\s+/g, ' ').trim().toLocaleLowerCase().match(/(-?"[^"]+"|[^"\s]+)/g) || []
  for (let i = 0; i < keywords.length; i++) {
    const negateWord = keywords[i].startsWith('-') ? true : false
    let word = keywords[i].replace(/^-/,'')
    const isPhraseRegex = word.startsWith('"') ? true : false
    if (isPhraseRegex) {
      word = word.replace(/^"(.+)"$/,"$1")
    }
    let word_in_item = false
    for (const field of fields) {
      if (item[field] && matchOrIncludes(item[field].toLocaleLowerCase(), word, isPhraseRegex)) {
        word_in_item = true
        break
      }
    }
    if ((! negateWord && ! word_in_item) || (negateWord && word_in_item)) {
      return false
    }
  }
  return true
}

const item = {title: 'My title', body: 'Some text'}
console.log(itemMatches(item, 'text', ['title', 'body']))

于 2020-10-20T15:00:40.183 に答える