Регулярное выражение для поиска неэкранированных двойных кавычек в файле CSV - PullRequest
3 голосов
/ 21 октября 2009

Что было бы регулярным выражением для поиска наборов из 2 неэкранированных двойных кавычек, содержащихся в столбцах, выделенных двойными кавычками в файле CSV?

Не соответствует:

"asdf","asdf"
"", "asdf"
"asdf", ""
"adsf", "", "asdf"

Match:

"asdf""asdf", "asdf"
"asdf", """asdf"""
"asdf", """"

Ответы [ 5 ]

3 голосов
/ 21 октября 2009

Попробуйте это:

(?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

Таким образом, на простом английском языке: "соответствует двум последовательным двойным кавычкам, только если они не имеют запятой или конца строки перед ними с произвольными пробелами и символами табуляции между" .

(i) помимо обычных начала строки и конца строки метасимволов.

2 голосов
/ 21 октября 2009

Из-за сложности вашей проблемы решение зависит от используемого вами двигателя. Это потому, что для ее решения вы должны использовать оглядываться назад и заглядывать в будущее, и каждый двигатель не тот же.

Мой ответ - использование движка Ruby. Проверка - это всего лишь один RegEx, но я приведу здесь весь код для лучшего объяснения.

ОБРАТИТЕ ВНИМАНИЕ, что из-за движка Ruby 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

Надеюсь, я дам вам некоторую идею, которую вы можете использовать с другим движком и языком.

0 голосов
/ 21 октября 2009

Попробуйте это регулярное выражение:

"(?:[^",\\]*|\\.)*(?:""(?:[^",\\]*|\\.)*)+"

Это будет соответствовать любой строке в кавычках хотя бы с одной парой неэкранированных двойных кавычек.

0 голосов
/ 21 октября 2009

Для однострочных матчей:

^("[^"]*"\s*,\s*)*"[^"]*""[^"]*"

или для нескольких строк:

(^|\r\n)("[^\r\n"]*"\s*,\s*)*"[^\r\n"]*""[^\r\n"]*"

Редактировать / Примечание: В зависимости от используемого движка регулярных выражений, вы можете использовать lookbehinds и другие вещи, чтобы сделать регулярное выражение более гибким. Но это должно работать в большинстве движков регулярных выражений просто отлично.

0 голосов
/ 21 октября 2009
".*"(\n|(".*",)*)

должно работать, я думаю ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...