1

これが私のジレンマです...

次のような文字列を分割できるようにしたい:

/ban @User "because I told you so"

ただし、文字列の区切り文字としてスペース、@、または引用符を使用する場合の問題は、ユーザー名にさまざまな特殊文字を含めることができることです。そして、おそらく、これらの特殊文字がコマンドの処理と競合する可能性があります。

例えば:

/ban @Person" "because why not"

うまくいかないだろう

/ban @Person"name" "reason"

文字列を分割するために使用できる文字のいずれかが、対象のユーザーの名前によって簡単にエミュレートされてコマンドを中断できる場合、このようなものを正確に処理するにはどうすればよいでしょうか? これはまったく可能ですか?正直に言うと、RegExp は私が理解したり調べたりするのが困難なため、これが単純な正規表現の修正である場合は、申し訳ありません :(

解決策のおかげで、私は今、作業中のプロセッサを持っています:

    var yourRegex = /^@(.*?) "([^"]+)"$/;

私はすでに /ban を取り除くことができるので (/kick などの他のコマンドは、この 1 つのコマンドだけではないため)、正規表現からそれを切り取っただけです。ユーザーをターゲットにする必要がないため、@ 記号も外しました。作品 100% :D

4

2 に答える 2

1

これを試して:

/^\/ban (@.*?) "([^"]+)"$/

これにより、最初のサブパターンにユーザー名が表示され(先頭の@記号で、除外する場合は括弧の外に移動するだけです)、2番目のサブパターンに理由が表示されます(引用符なしで、括弧内に移動してそれらを含めます) )。

于 2012-12-30T22:47:04.883 に答える
1

コメントで述べたように、最小限のパーサーを使用して同様のタスクに取り組みました。JavaScript にコンパイルされる CoffeeScript の例を次に示します。

parse = (input) ->
  index = 0
  peek = -> input.charAt index
  advance = -> ++index; peek()
  advanceRP = ->
    last = peek()
    advance()
    return last
  collect = (regex) -> (advanceRP() while peek().match regex).join ''
  skipWhiteSpace = -> collect /\s/
  literal = ->
    result = collect /[@\w]/
    skipWhiteSpace()
    return result
  string = ->
    if peek() == '"'
      advance()
      result = []
      loop
        result.push collect /[^"]/
        advance()  # skip past closing quote
        if peek() is '"'  # and therefore an escape (double quote)
          result.push '"'
        else if peek().match /\s?/
          break  # whitespace or end of input; end of string
        else
          # neither another quote nor whitespace;
          # they probably forgot to escape the quote.
          # be lenient, here.
          result.push '"'
      skipWhiteSpace()
      result.join ''
    else
      literal()

  return error: 'does not start with slash' if peek() isnt '/'
  advance()
  command = literal()
  return error: 'command unrecognized' if command isnt 'ban'
  person = string()
  if peek() == '"'
    reason = string()
    return error: 'junk after end of command' if index < input.length
  else
    reason = input.substring index

  command: 'ban'
  person: person
  reason: reason

やってみて:

coffee> parse '/ban @person reason'
{ command: 'ban', person: '@person', reason: 'reason' }
coffee> parse '/ban "@person with ""escaped"" quotes" and the reason doesn\'t need "quotes"'
{ command: 'ban'
, person: '@person with "escaped" quotes'
, reason: 'and the reason doesn\'t even need "quotes"'
}
于 2012-12-30T23:21:44.650 に答える