質問
これが可能かどうか確信が持てないので、あなたに振り返ります。
引用セットの外にあるすべてのコンマを選択する正規表現を見つけたいです。
例:
'foo' => 'bar',
'foofoo' => 'bar,bar'
これにより、1行目の 'bar'の後の単一のコンマが選択されます。
一重引用符と二重引用符はあまり気にしません。
何か考えがありますか?先読みでこれが可能になるはずですが、正規表現のfuは弱すぎます。
解決
これは、引用符で囲まれていない最初の"、"までの文字列に一致します。それはあなたが望んでいるものですか?
/^([^"]|"[^"]*")*?(,)/
それらすべてを(そしてそれは不可能だと言った男の反例として)欲しいなら、あなたはこう書くことができます:
/(,)(?=(?:[^"]|"[^"]*")*$)/
これらはすべて一致します。したがって
'test, a "comma,", bob, ",sam,",here'.gsub(/(,)(?=(?:[^"]|"[^"]*")*$)/,';')
引用符内のすべてのコンマをセミコロンでではなく置き換え、以下を生成します。
'test; a "comma,"; bob; ",sam,";here'
改行を越えて動作する必要がある場合は、m(複数行)フラグを追加してください。
他のヒント
以下の正規表現は、二重引用符の外側にあるすべてのコンマと一致します
,(?=(?:[^"]*"[^"]*")*[^"]*$)
または(PCREのみ)
"[^"]*"(*SKIP)(*F)|,
" [^"] *"
は、二重引用符で囲まれたすべてのブロックに一致します。つまり、この buz、" bar、foo"
入力では、この正規表現は" bar、foo"
のみに一致します。これで、次の(* SKIP)(* F)
が一致を失敗させます。次に、 |
シンボルの隣にあるパターンに移動し、残りの文字列の文字との一致を試みます。つまり、出力で、パターン
は、 |
の横の buz
の直後にあるコンマのみに一致します。これは、二重引用符で囲まれた部分をスキップするように既に作成しているため、二重引用符内に存在するコンマとは一致しないことに注意してください。
以下の正規表現は、二重引用符内にあるすべてのコンマに一致します
,(?!(?:[^"]*"[^"]*")*[^"]*$)
正規表現でハッキングすることは可能ですが(次の人と同じように正規表現を悪用することを楽しんでいます)、遅かれ早かれ、より高度なパーサーなしで部分文字列を処理しようとすると問題が発生します。問題を起こす可能性のある方法には、引用符の混在、引用符のエスケープなどがあります。
この関数はコンマで文字列を分割しますが、単一引用符または二重引用符で囲まれたコンマでは分割しません。引用符として使用する追加の文字で簡単に拡張できます(ただし、«»のような文字のペアにはさらに数行のコードが必要になります)。データの引用符を閉じるのを忘れた場合でも通知されます:
function splitNotStrings(str){
var parse=[], inString=false, escape=0, end=0
for(var i=0, c; c=str[i]; i++){ // looping over the characters in str
if(c==='\\'){ escape^=1; continue} // 1 when odd number of consecutive \
if(c===','){
if(!inString){
parse.push(str.slice(end, i))
end=i+1
}
}
else if(splitNotStrings.quotes.indexOf(c)>-1 && !escape){
if(c===inString) inString=false
else if(!inString) inString=c
}
escape=0
}
// now we finished parsing, strings should be closed
if(inString) throw SyntaxError('expected matching '+inString)
if(end<i) parse.push(str.slice(end, i))
return parse
}
splitNotStrings.quotes="'\"" // add other (symmetrical) quotes here
この正規表現を試してください:
(?:"(?:[^\\"]+|\\(?:\\\\)*[\\"])*"|'(?:[^\\']+|\\(?:\\\\)*[\\'])*')\s*=>\s*(?:"(?:[^\\"]+|\\(?:\\\\)*[\\"])*"|'(?:[^\\']+|\\(?:\\\\)*[\\'])*')\s*,
これは、「 'foo \' bar '=&gt;」などの文字列も許可します。 「bar \\」、
」。
MarkusQの答えは、うまくいかなくなるまで、約1年間私にとってはうまくいきました。約120個のコンマと合計3682文字の行でスタックオーバーフローエラーが発生しました。 Javaの場合:
String[] cells = line.split("[\t,](?=(?:[^\"]|\"[^\"]*\")*$)", -1);
これは、スタックオーバーフローを起こさない、非常にエレガントな代替品です。
private String[] extractCellsFromLine(String line) {
List<String> cellList = new ArrayList<String>();
while (true) {
String[] firstCellAndRest;
if (line.startsWith("\"")) {
firstCellAndRest = line.split("([\t,])(?=(?:[^\"]|\"[^\"]*\")*$)", 2);
}
else {
firstCellAndRest = line.split("[\t,]", 2);
}
cellList.add(firstCellAndRest[0]);
if (firstCellAndRest.length == 1) {
break;
}
line = firstCellAndRest[1];
}
return cellList.toArray(new String[cellList.size()]);
}
@ SocialCensus、MarkusQへのコメントで指定した例は、&quot;の横に 'を挿入しますが、MarkusQが sam を sam's :(テスト、「コンマ」、bob、「sam's」、ここでは)は(、)(?=(?:[^&quot; ' ] | [&quot; | '] [^&quot;'] &quot;) $)。実際、「シングルクォートとダブルクォートのどちらでも構いません」という問題自体はあいまいです。 &quot;のいずれかで引用することで、意味を明確にする必要があります。または 'で。たとえば、ネストは許可されていますか?もしそうなら、何レベルまで?ネストされたレベルが1つだけの場合、内側のネストされた引用の外側で、外側のネストされた引用の内側のコンマはどうなりますか?また、単一引用符はそれ自体でアポストロフィとして発生することを検討する必要があります(つまり、以前にsamで示した反例のように)。最後に、あなたが作った正規表現は、最後のタイプの引用符が必然的に二重引用符であると想定しているため、実際に二重引用符でパーの単一引用符を扱いません-そして最後の二重引用符を['|&quot;]で置き換えることもテキストに正しい引用符が付いていない場合(またはアポストロフィが使用されている場合)に問題がありますが、おそらくすべての引用符が正しく記述されていると想定できると思います。
MarkusQの正規表現は質問に答えます:二重引用符の後に偶数の二重引用符がある(つまり二重引用符の外側にある)すべてのコンマを見つけ、その後に二重引用符の奇数があるすべてのコンマを無視します(つまり二重内にあります)引用符)。これは一般的におそらくあなたが望むものと同じ解決策ですが、いくつかの異常を見てみましょう。最初に、誰かが最後に引用符を付けない場合、この正規表現は、目的のコンマを見つけたり、いずれにも一致しなかったりするのではなく、間違ったコンマをすべて見つけます。もちろん、二重引用符が欠落している場合、欠落しているものが最後に属しているか、代わりに先頭に属しているかが明確でない可能性があるため、すべてのベットはオフになります。ただし、正当であり、正規表現がおそらく失敗する可能性がある場合があります(これが2番目の「異常」です)。テキスト行にまたがるように正規表現を調整する場合、連続する複数の段落を引用するには、各段落の先頭に単一の二重引用符を付け、各段落の末尾にある引用符を除く必要があることに注意してください最後の段落の終わり。つまり、これらの段落のスペースでは、正規表現はある場所では失敗し、別の場所では成功します。
段落の引用とネストされた引用の例と簡単な説明は、ここ http://en.wikipediaにあります。 .org / wiki / Quotation_mark 。