Я не уверен, если это возможно, хотя варианты, но вот регулярное выражение, которое достигает того, что вы хотите.
structure = {
"a" => {"b" => 1},
"c" => [2],
"d" => [],
"e" => {},
"f" => "string with [ ] and { }"
}
json = JSON.pretty_generate(structure)
regex = /(?<content>"(?:[^\\"]|\\.)+")|(?<open>\{)\s+(?<close>\})|(?<open>\[)\s+(?<close>\])/m
puts json.gsub(regex, '\k<open>\k<content>\k<close>')
# {
# "a": {
# "b": 1
# },
# "c": [
# 2
# ],
# "d": [],
# "e": {},
# "f": "string with [ ] and { }"
# }
#=> nil
Используемое регулярное выражение начинает совпадать либо с "
, [
или {
символ.
Если он начинает совпадать с "
, он будет совпадать до конца строки, игнорируя все промежуточные значения. Захват всей строки в группе content
. Группы open
и close
будут пустыми. При замене на gsub
вся группа content
будет возвращена обратно. Это делается для отмены {
и [
символов в строковом контексте.
Если он начинает совпадение с [
или {
, он допускает только пробельные символы и ищет соответствующие ]
или}
. Открывающий и закрывающий символы будут помещены в группы open
и close
соответственно, промежуточный пробел не будет захвачен. Группа content
будет пустой. Только группы open
и close
будут помещены обратно при замене (удаление пробельных символов).
Вот схема соответствия. Он не любил именованные группы, поэтому я удалил их, чтобы отобразить диаграмму. group #1
соответствуют content
, group #2
и group #4
соответствуют open
, group #3
и group #5
соответствуют close
.