التعبير العادي أن تجد unescaped التنصيص في ملف CSV
سؤال
ما من شأنه أن التعبير العادي يكون العثور على مجموعات من 2 unescaped علامات الاقتباس المزدوجة الموجودة في الأعمدة انطلقت من علامات الاقتباس المزدوجة في ملف CSV?
ليست مباراة:
"asdf","asdf"
"", "asdf"
"asdf", ""
"adsf", "", "asdf"
المباراة:
"asdf""asdf", "asdf"
"asdf", """asdf"""
"asdf", """"
المحلول
جرب هذا:
(?m)""(?![ \t]*(,|$))
التفسير:
(?m) // enable multi-line matching (^ will act as the start of the line and $ will act as the end of the line (i))
"" // match two successive double quotes
(?! // start negative look ahead
[ \t]* // zero or more spaces or tabs
( // open group 1
, // match a comma
| // OR
$ // the end of the line or string
) // close group 1
) // stop negative look ahead
حتى في سهل الانجليزية: "مباراة متتاليتين التنصيص ، إلا إذا لم يكن لديهم فاصلة أو نهاية الخط أمامهم مع اختياريا المسافات بين علامات التبويب في".
(ط) إلى جانب كونها طبيعية بداية من سلسلة و نهاية السلسلة ميتا الشخصيات.
نصائح أخرى
بسبب تعقيد المشكلة ، الحل يعتمد على المحرك الذي تستخدمه.هذا لأن لحلها يجب استخدام ننظر وراء ونتطلع إلى الأمام و كل محرك ليست نفس واحدة هذا.
جوابي هو باستخدام روبي المحرك.فحص واحد فقط RegEx لكن كل رمز هنا شرح ذلك بصورة أفضل.
ملاحظة أنه نظرا روبي RegEx المحرك (أو المعرفة) ، الاختياري نتطلع إلى الأمام/الخلف غير ممكن.لذلك أنا بحاجة مشكلة صغيرة من مسافات قبل وبعد الفاصلة.
هنا هو بلدي رمز:
orgTexts = [
'"asdf","asdf"',
'"", "asdf"',
'"asdf", ""',
'"adsf", "", "asdf"',
'"asdf""asdf", "asdf"',
'"asdf", """asdf"""',
'"asdf", """"'
]
orgTexts.each{|orgText|
# Preprocessing - Eliminate spaces before and after comma
# Here is needed if you may have spaces before and after a valid comma
orgText = orgText.gsub(Regexp.new('\" *, *\"'), '","')
# Detect valid character (non-quote and valid quote)
resText = orgText.gsub(Regexp.new('([^\"]|^\"|\"$|(?<=,)\"|\"(?=,)|(?<=\\\\)\")'), '-')
# resText = orgText.gsub(Regexp.new('([^\"]|(^|(?<=,)|(?<=\\\\))\"|\"($|(?=,)))'), '-')
# [^\"] ===> A non qoute
# | ===> or
# ^\" ===> beginning quot
# | ===> or
# \"$ ===> endding quot
# | ===> or
# (?<=,)\" ===> quot just after comma
# \"(?=,) ===> quot just before comma
# (?<=\\\\)\" ===> escaped quot
# This part is to show the invalid non-escaped quots
print orgText
print resText.gsub(Regexp.new('"'), '^')
# This part is to determine if there is non-escaped quotes
# Here is the actual matching, use this one if you don't want to know which quote is un-escaped
isMatch = ((orgText =~ /^([^\"]|^\"|\"$|(?<=,)\"|\"(?=,)|(?<=\\\\)\")*$/) != 0).to_s
# Basicall, it match it from start to end (^...$) there is only a valid character
print orgText + ": " + isMatch
print
print ""
print ""
}
عندما أعدم قانون المطبوعات:
"asdf","asdf"
-------------
"asdf","asdf": false
"","asdf"
---------
"","asdf": false
"asdf",""
---------
"asdf","": false
"adsf","","asdf"
----------------
"adsf","","asdf": false
"asdf""asdf","asdf"
-----^^------------
"asdf""asdf","asdf": true
"asdf","""asdf"""
--------^^----^^-
"asdf","""asdf""": true
"asdf",""""
--------^^-
"asdf","""": true
أتمنى أن تعطيك فكرة هنا يمكنك استخدامها مع غيرها من محرك واللغة.
".*"(\n|(".*",)*)
يجب أن أعمل...
واحد خط المباريات:
^("[^"]*"\s*,\s*)*"[^"]*""[^"]*"
أو متعدد الخطوط:
(^|\r\n)("[^\r\n"]*"\s*,\s*)*"[^\r\n"]*""[^\r\n"]*"
تحرير/ملاحظة: اعتمادا على regex المحرك المستخدم ، يمكن استخدام lookbehinds وغيرها من الأشياء لجعل regex أصغر حجما.ولكن هذا يجب أن تعمل في معظم regex محركات على ما يرام.
جرب هذا التعبير العادية:
"(?:[^",\\]*|\\.)*(?:""(?:[^",\\]*|\\.)*)+"
من شأنها أن تتطابق مع أي سلسلة مقتبسة مع زوج واحد على الأقل من unescaped علامات الاقتباس المزدوجة.