次のような文字列を解析するために必要な正規表現を誰かが提供してくれるのではないかと思います。
'foo bar "複数単語タグ"'
次のようなタグの配列に
[「foo」、「bar」、「複数単語タグ」]
ありがとう
ルビーで
scan(/\"([\w ]+)\"|(\w+)/).flatten.compact
例えば
"foo bar \"multiple words\" party_like_1999".scan(/\"([\w ]+)\"|(\w+)/).flatten.compact
=> ["foo", "bar", "multiple words", "party_like_1999"]
これを行うためにスキャナーを実装できます。たとえば、Python では次のようになります。
import re
scanner = re.Scanner([
(r"[a-zA-Z_]\w*", lambda s,t:t), # regular tag
(r"\".*?\"", lambda s,t:t[1:-1]), # multi-word-tag
(r"\s+", None), # whitespace not in multi-word-tag
])
tags, _ = scanner.scan('foo bar "multiple word tag"')
print tags
# ['foo', 'bar', 'multiple word tag']
これを字句解析と呼びます。
まず、split()
正規表現ではなく、メソッド/関数を使用してこれを行うことをお勧めします。ほとんどの言語には、文字列を (空白で区切られた) 単語に分割するために呼び出すことができるこのようなものがあります。通常、分割する部分の数の上限を指定できます。したがって、一般的に、
split('foo bar "multiple word tag"', ' ', 3)
ここで、3 は 3 つ以下のパーツであることを示しますが、この例では機能します。trim()
またはメソッド/関数を使用strip()
(または記述) して、先頭と末尾の引用符を削除できます。
おそらく各行に可変数のタグが含まれている可能性があるため、正規表現でそれを行うつもりなら、ある程度、解析を行うために正確に何を使用しているかに依存します。同じものを表しています。そして、単純な古い正規表現だけでそれができるとは思いません。それに伴うコードが必要になります。たとえば、Perl 互換の正規表現 (またはそれに類するもの) を使用した (疑似?) 疑似コード ソリューションは次のとおりです。
pos = 0;
while pos < length(string):
# match(regular expression, string to search, starting position for the search)
m = match(/\s*(".+?"|\S+)?\s*/, string, pos);
tag = m.group(1).strip('"');
# process the tag
価値があるのは、おそらくこれをDFA(離散有限オートマトン)で行うことです。DFAは、文字列を1文字ずつバッファに追加し、タグの最後に達したときにバッファをフラッシュします(スペースまたは閉じ引用符)。多分それは私だけかもしれませんが、これは非常に単純な解析タスクであり、DFA の状態に関して (私の考えでは) 理解しやすいと思います。
任意の match->array 関数で機能する一般的な正規表現:
(?<=")[^"]+|\w+
(英数字と引用符以外が許可されている場合は、\S+
代わりに使用するの\w+
が理にかなっている可能性があります。)
ルビーの例:
myarray = mystring.scan(/(?<=\")[^\"]+|\w+/)
(未テスト)
では、どうぞ (Perl スタイル):
^(?:"([^"]*?)"|(\S+?)|\s*?)*$
説明:
^ // from begginning
(?: // non-capturing group of three alternatives
"([^"]*?)" // capture "tag" "
|
(\S+?) // capture tag
|
\s*? // ignore whitespace
)*
$ // until the end of the line
正規表現は、ここで探しているソリューションではないことはほぼ確実です。正規表現は、より大きな文字列から一致した入力のセットを解析するのに役立ちます。たとえば、メール アドレスからユーザー名を取得したい場合は、次の正規表現を使用してデータを取得できます。
"^(?<username>[\w\d]+)@.*$"
名前は名前グループ「username」に存在します
あなたの場合、入力文字列のサブセットを取得しようとしていません。文字列全体の要素を一致させようとしています。結局のところ、正規表現は「はい、一致します」または「いいえ、一致しません」と言うだけです。内容を取得するには、実際に文字列を解析する必要があります。