我在多行字符串中并排有两个地址:
Adresse de prise en charge : Adresse d'arrivée :
rue des capucines rue des tilleuls
92210 Saint Cloud 67000 Strasbourg
Tél.: Tél.:
我需要使用regexp在左侧和右侧提取地址,并将它们分配给变量。我需要匹配:
address1
:"rue des capucines 92210 Saint Cloud"
address2
:"rue des tilleuls 67000 Strasbourg"
我想过用空格分隔它们,但我找不到任何正则表达式来计算空格。我试过了:
en\s*charge\s*:\s*((.|\n)*)\s*
和类似,但这给了我两个地址,而不是我正在寻找的。任何帮助都将深表感谢。
答案 0 :(得分:3)
我会做这样的事情:
str = <<EOT
Adresse de prise en charge : Adresse d'arrivée :
rue des capucines rue des tilleuls
92210 Saint Cloud 67000 Strasbourg
Tél.: Tél.:
EOT
left_addr = []
right_addr = []
lines = str.squeeze("\n").gsub(':', '').lines.map(&:strip) # => ["Adresse de prise en charge Adresse d'arrivée", "rue des capucines rue des tilleuls", "92210 Saint Cloud 67000 Strasbourg", "Tél. Tél."]
center_line_pos = lines.max.length / 2 # => 35
lines.each do |l|
left_addr << l[0 .. (center_line_pos - 1)].strip
right_addr << l[center_line_pos .. -1].strip
end
此时left_addr
和right_addr
看起来像:
left_addr # => ["Adresse de prise en charge", "rue des capucines", "92210 Saint Cloud", "Tél."]
right_addr # => ["Adresse d'arrivée", "rue des tilleuls", "67000 Strasbourg", "Tél."]
以下是它们的内容:
puts left_addr
puts '------'
puts right_addr
# >> Adresse de prise en charge
# >> rue des capucines
# >> 92210 Saint Cloud
# >> Tél.
# >> ------
# >> Adresse d'arrivée
# >> rue des tilleuls
# >> 67000 Strasbourg
# >> Tél.
如果您需要结果全部在一行而没有'Tel:':
puts left_addr[0..-2].join(' ').squeeze(' ')
puts '------'
puts right_addr[0..-2].join(' ').squeeze(' ')
# >> Adresse de prise en charge rue des capucines 92210 Saint Cloud
# >> ------
# >> Adresse d'arrivée rue des tilleuls 67000 Strasbourg
以下是对发生情况的细分:
str.squeeze("\n") # => " Adresse de prise en charge : Adresse d'arrivée :\n rue des capucines rue des tilleuls\n 92210 Saint Cloud 67000 Strasbourg\n Tél.: Tél.:\n"
.gsub(':', '') # => " Adresse de prise en charge Adresse d'arrivée \n rue des capucines rue des tilleuls\n 92210 Saint Cloud 67000 Strasbourg\n Tél. Tél.\n"
.lines # => [" Adresse de prise en charge Adresse d'arrivée \n", " rue des capucines rue des tilleuls\n", " 92210 Saint Cloud 67000 Strasbourg\n", " Tél. Tél.\n"]
.map(&:strip) # => ["Adresse de prise en charge Adresse d'arrivée", "rue des capucines rue des tilleuls", "92210 Saint Cloud 67000 Strasbourg", "Tél. Tél."]
答案 1 :(得分:2)
假设每行中的每个地址部分都缩进与第一行中相应的"Adresse"
一样多或更远,以下内容不仅可以提取两个对齐的地址,而且通常可以提取n个地址。
lines = string.split(/#{$/}+/)
# => [
# => "Adresse de prise en charge : Adresse d'arrivée :",
# => " rue des capucines rue des tilleuls",
# => " 92210 Saint Cloud 67000 Strasbourg",
# => " Tél.: Tél.:"
# => ]
break_points = []
lines.first.scan(/\bAdresse\b/){break_points.push($~.begin(0))}
ranges = break_points.push(0).each_cons(2).map{|s, e| s..(e - 1)}
# => [0..53, 54..-1]
address1, address2 =
lines[1..-2]
.map{|s| ranges.map{|r| s[r]}}
.transpose
.map{|a| a.join(" ").strip.squeeze(" ")}
# => [
# => "rue des capucines 92210 Saint Cloud",
# => "rue des tilleuls 67000 Strasbourg"
# => ]
答案 2 :(得分:2)
<强>假设强>
我假设不需要第一行和最后一行,街道名称至少由两个空格分隔,邮政编码/城市字符串相同。这允许“奖金收费”的街道名称(和邮政编码/城市对)在“Adresse d'arrivée:”之后结束。
<强>代码强>
def parse_text(text)
text.split(/\n+\s+/)[1..-2].
map { |s| s.gsub(/\d+\K\s+/,' ').split(/\s{2,}/) }.
transpose.
map { |a| a.join(' ') }
end
<强>实施例强>
示例1
text = <<BITTER_END
Adresse de prise en charge : Adresse d'arrivée :
rue des capucines rue des tilleuls
92210 Saint Cloud 67000 Strasbourg
Tél.: Tél.:
BITTER_END
parse_text(text)
#=> ["rue des capucines 9210 Saint Cloud",
# "rue des tileuls 670 Strasbourg"]
示例2
text = <<_
Adresse 1 : Adresse 2 : Adresse 3 :
rue nom le plus long du monde par un mile rue gargouilles rue des tilleuls
92210 Saint Cloud 31400 Nice 67000 Strasbourg
France France France
Tél.: Tél.: Tél.:
_
parse_text(text)
#=> ["rue nom le plus long du monde par un mile 92210 Saint Cloud France",
# "rue gargouilles 31400 Nice France",
# "rue des tilleuls 67000 Strasbourg France"]
<强>解释强>
问题中给出text
的步骤:
拆分成行,删除空行和前导空格:
a1 = text.split(/\n+\s+/)
#=> ["Adresse de prise en charge : Adresse d'arrivée :",
# "rue des capucines rue des tilleuls",
# "92210 Saint Cloud 67000 Strasbourg",
# "Tél.: Tél.:\n"]
删除第一行和最后一行:
a2 = a1[1..-2]
#=> ["rue des capucines rue des tilleuls",
# "92210 Saint Cloud 67000 Strasbourg"]
删除邮政编码和城市之间的额外空格,并将每一行拆分为两个或多个空格:
r = /
\d+ # match one or more digits
\K # forget everything matched so far
\s+ # match one of more spaces
/x # extended/free-spacing regex definition mode
a3 = a2.map { |s| s.gsub(/\d+\K\s+/,' ').split(/\s{2,}/) }
#=> [["rue des capucines", "rue des tilleuls"],
# ["92210 Saint Cloud", "67000 Strasbourg"]]
按列分组:
a4 = a3.transpose
#=> [["rue des capucines", "92210 Saint Cloud"],
# ["rue des tilleuls", "67000 Strasbourg"]]
加入字符串:
a4.map { |a| a.join(' ') }
#=> ["rue des capucines 92210 Saint Cloud",
# "rue des tilleuls 67000 Strasbourg"]
答案 3 :(得分:2)
str =
" Adresse de prise en charge : Adresse d'arrivée :
rue des capucines rue des tilleuls
92210 Saint Cloud 67000 Strasbourg
Tél.: Tél.:"
adr_prise, adr_arr = str.lines[3].strip.split(/ {2,}/) #split on 2+ spaces
code_prise, cite_prise, code_arr, cite_arr = str.lines[6].strip.split(/ {2,}/)
答案 4 :(得分:1)
受到@steenslag's very pragmatic answer的启发,这是一个非常密集的单行内容,只是为了好玩。
# Assume the input data is in the variable `text`
left_addr, right_addr = text.lines.values_at(3, 6).map do |line|
line.scan(/(?:\d+ +)?\S+(?: \S+)*/)
.map {|part| part.squeeze(' ') }
end
.transpose
.map {|addr| addr.join(' ') }
puts left_addr
# => rue des capucines 92210 Saint Cloud
puts right_addr
# => rue des tilleuls 67000 Strasbourg
与@ steenslag的答案一样,这假设所需的数据总是在第3和第6行。它还假设在第6行,两列都有一个邮政编码和城市,邮政编码将始终开始有一个数字。
因为它是一个非常密集的单行,因为它做了很多假设,我不认为这是最好的答案,我将它标记为社区维基。
如果我有时间,我会稍后再回来解压缩。
答案 5 :(得分:0)
假设“中心线位置”已知,这将起作用:
left_lines, right_lines = str.scan(/^(.{50})(.*)$/).transpose
正则表达式在每行的开头捕获50个字符加上剩余的字符,直到行结束。
scan
返回一个嵌套数组:(我正在使用占位符,因为实际的行太长了)
[
['1st left line', '1st right line'],
['2nd left line', '2nd right line'],
...
]
transpose
将其转换为:
[
['1st left line', '2nd left line', ...], # <- assigned to left_lines
['1st right line', '2nd right line', ...] # <- assigned to right_lines
]
行(不包括第一行和最后一行)必须为join
,并且必须删除空格:(请参阅strip
和squeeze
)
left_lines[1..-2].join(' ').strip.squeeze(' ')
#=> "rue des capucines 92210 Saint Cloud"
right_lines
相同:
right_lines[1..-2].join(' ').strip.squeeze(' ')
#=> "rue des tilleuls 67000 Strasbourg"