Regex для выбора новой строки между кавычками - PullRequest
0 голосов
/ 25 марта 2019

У меня есть строка в Ruby, похожая на следующую:

{
  "a boolean": true,
  "multiline": "
my
multiline
value
",
  "a normal key": "a normal value"
}

Я бы хотел сопоставить только символы новой строки в подстроке:

"
my
multiline
value
",

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

Ответы [ 5 ]

2 голосов
/ 29 марта 2019

UPdate - Эти регулярные выражения работают как положено.
От @faissaloo - it seemed to fail however on my large JSON .
Я запустил эту большую строку, используяоба regex:
PCRE https://regex101.com/r/3jtqea/1
Ruby https://regex101.com/r/1HVCCC/1
Они оба работают одинаково и без недостатков.
Если у вас есть какие-либо другие проблемы, пожалуйста, дайте мне знать.


Я думаю, что Ruby поддерживает Perl-подобные конструкции.
Если это так, то это можно сделать одним глобальным поиском и заменой.
Примерно так:

Редактировать - Ruby не выполняет возвратные глаголы управления (*SKIP)(*FAIL)
, поэтому для этого в коде Ruby требуется, чтобы регулярное выражение было более явным.
Итак, с небольшой модификацией pcre /Perl Regex, эквивалент Ruby:

Ruby
Найти

(?-m)((?!\A)\G|(?:(?>[^"]*"[^"\r\n]*"[^"]*))*")([^"\r\n]*)\K\r?\n(?=[^"]*")((?:[^"\r\n]*"(?:(?>[^"]*"[^"\r\n]*"))*[^"]*)?)

Заменить

\\n\3

https://regex101.com/r/BaqjEE/1
https://rextester.com/NVFD38349

Объяснил (но это сложно)

 (?-m)                                    # Non-multiline mode safety check
 (                                        # (1 start), Prefix. Capture for debug
      (?! \A )                                 # Not BOS
      \G                                       # Test where last match left off

   |                                         # or, 
      (?:                                      # Optionally align to next " ( only used once )
           (?> [^"]* " [^"\r\n]* " [^"]* )
      )*

      "                                        # A new quote to test
 )                                        # (1 end)

 ( [^"\r\n]* )                            # (2), Line break Preamble. Capture for debug
 \K                                       # Exclude from the match (group 0) up to this point

 \r? \n                                   # Line break to escape

 (?= [^"]* " )                            # Validate we have " closure

 (                                        # (3 start), Optional end quote and alignment.
                                               # To be written back.
      (?:
           [^"\r\n]* "                   
           (?:                                      # Optionally align to next "
                (?> [^"]* " [^"\r\n]* " )
           )*
           [^"]* 
      )?
 )                                        # (3 end)


 # Ruby Code:
 #----------------------
 # #ruby 2.3.1 
 # 
 # re = /(?-m)((?!\A)\G|(?:(?>[^"]*"[^"\r\n]*"[^"]*))*")([^"\r\n]*)\K\r?\n(?=[^"]*")((?:[^"\r\n]*"(?:(?>[^"]*"[^"\r\n]*"))*[^"]*)?)/
 # str = '{
 #   "a boolean": true,
 #   "a boolean": true,
 #   "a boolean": true,
 #   "a boolean": true,
 #   "multiline": "
 # my
 # multiline
 # value
 # asdf"
 # ,
 # 
 # "a multiline boo
 # lean": true,
 # "a normal key": "a multiline
 # 
 # value"
 # }'
 # subst = '\\n\3'
 # 
 # result = str.gsub(re, subst)
 # 
 # # Print the result of the substitution
 # puts result

Для Pcre / Perl
Найти

(?:((?:(?>[^"]*"[^"\n]*"[^"]*))+(*SKIP)(*FAIL)|"|(?!^)\G)([^"\n]*)\K\n(?=[^"]*")((?:[^"\n]*")?))

Заменить

\\n$3

https://regex101.com/r/06naae/1

Объяснено (но это сложно)
Обратите внимание, если вы находитесь в окне Windows, где редакторам нужны разрывы CRLF,
добавьте \r перед LF, какэто \r\n.

 (?:
      (                             # (1 start), Prefix capture, for debug
           (?:
                (?> [^"]* " [^"\n]* " [^"]* )
           )+
           (*SKIP) (*FAIL)               # Consume false positives, but ignore them
                                         # (need this to align next ")
        |                              # or,
           "                             # A new quote to test
        |                              # or, 
           (?! ^ )                       # Not BOS
           \G                            # Test where last match left off
      )                             # (1 end)

      ( [^"\n]* )                   # (2), Preamble capture, for debug
      \K                            # Exclude from the match (group 0) up to this point
      \n                            # Line break to escape
      (?= [^"]* " )                 # Validate we have " closure
      (                             # (3 start), End quote, to be written back
           (?: [^"\n]* " )?
      )                             # (3 end)
 )
1 голос
/ 28 марта 2019

Я думаю, что это может вам помочь.Вы захватываете \n внутри строки и затем можете заменить его:

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

Проверьте его

0 голосов
/ 03 апреля 2019

Если ваши многострочные строки не содержат запятых (непосредственно перед разрывом строки), то вы можете использовать это в json, каждая строка должна заканчиваться ,, { или [, или следующая строка должна начать с } или ]:

json_string.gsub(/(?<!,|\{|\[)\n(?!\s*[}\]])/, '\n')

Если у вас есть запятые в строках (или фигурные и квадратные скобки), вы можете улучшить этот подход, добавив дополнительные сведения в список допустимых окончаний строк:

valid_line_ends = %w(true, false, ", }, ], { [)
line_end_matcher = valid_line_ends.map(&Regexp.method(:escape)).join('|')
json_string.gsub(/(?<!#{line_end_matcher})\n(?!\s*[}\]])/, '\n')
0 голосов
/ 02 апреля 2019

Поздний ответ, но вы можете использовать регулярные выражения, такие как:

'"(?=\n).*?"'

Соответствует:

"
    my
        multiline
    value
        ",

Демо-версия:

  1. Демонстрация и объяснение регулярных выражений
0 голосов
/ 28 марта 2019

Другой вариант будет выглядеть примерно так:

string = '{
  "a boolean": true,
  "multiline": "my
multiline
value",
  "a normal value"
}'

puts string.match(/"(\w+)(\n+\w*)+"/).to_s.gsub!("\n", '\n')

Это соответствует регулярному выражению в вашей строке и затем заменяет символы новой строки на экранированные символы новой строки.

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