ruby 中的格式字符串(邮政编码)

Posted

技术标签:

【中文标题】ruby 中的格式字符串(邮政编码)【英文标题】:format string (postcode) in ruby 【发布时间】:2010-04-08 09:06:37 【问题描述】:

我需要重新格式化英国邮政编码列表,并从以下内容开始去除空格并大写:

postcode.upcase.gsub(/\s/,'')

我现在需要更改邮政编码,以便新邮政编码的格式与以下正则表达式匹配:

^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? 1,2[0-9][ABD-HJLN-UW-Z]2|GIR 0AA)$

如有任何帮助,我将不胜感激。

【问题讨论】:

【参考方案1】:

如果要相信this standards doc(和***concurs),格式化一个有效的邮政编码输出很简单:最后三个字符是第二部分,之前的所有内容都是第一部分!

所以假设你有一个有效的邮政编码,没有任何预先嵌入的空间,你只需要

def format_post_code(pc)
  pc.strip.sub(/([A-Z0-9]+)([A-Z0-9]3)/, '\1 \2')
end

如果您想首先验证输入的邮政编码,那么您提供的正则表达式看起来是一个很好的起点。也许是这样的?

NORMAL_POSTCODE_RE = /^([A-PR-UWYZ][A-HK-Y0-9][A-HJKS-UW0-9]?[A-HJKS-UW0-9]?)\s*([0-9][ABD-HJLN-UW-Z]2)$/i
GIROBANK_POSTCODE_RE = /^GIR\s*0AA$/i
def format_post_code(pc)
  return pc.strip.upcase.sub(NORMAL_POSTCODE_RE, '\1 \2') if pc =~ NORMAL_POSTCODE_RE
  return 'GIR 0AA' if pc =~ GIROBANK_POSTCODE_RE
end

请注意,我删除了第一个字符的“0-9”部分,根据我引用的来源,这似乎是不必要的。我还更改了 alpha 集以匹配第一个引用的文档。它仍然不完美:例如,验证格式为“AAA ANN”的代码,我认为可能需要更复杂的 RE。

我认为这可能会涵盖它(分阶段构建以便于修复!)

A1  = "[A-PR-UWYZ]"
A2  = "[A-HK-Y]"
A34 = "[A-HJKS-UW]"        # assume rule for alpha in fourth char is same as for third
A5  = "[ABD-HJLN-UW-Z]"
N   = "[0-9]"
AANN = A1 + A2 + N + N     # the six possible first-part combos
AANA = A1 + A2 + N + A34
ANA  = A1 + N + A34
ANN  = A1 + N + N
AAN  = A1 + A2 + N
AN   = A1 + N
PART_ONE = [AANN, AANA, ANA, ANN, AAN, AN].join('|') 
PART_TWO = N + A5 + A5

NORMAL_POSTCODE_RE = Regexp.new("^(#PART_ONE)[ ]*(#PART_TWO)$", Regexp::IGNORECASE)  

【讨论】:

感谢迈克正是我想要的 :)【参考方案2】:

英国邮政编码不一致,但它们是有限的 - 使用查找表可能会更好。

【讨论】:

【参考方案3】:

重新格式化或模式匹配?我怀疑是后者,尽管先升级它是个好主意。

在我们继续之前,虽然我会指出您正在剥离空格,但您的正则表达式包含“1,2”,即“一个或两个空格字符”。由于您已经剥离了空格,因此您已经导致所有匹配失败。

给定一个邮政编码作为输入,我们可以使用 =~ 来检查它是否与正则表达式匹配

这里我们创建了一些示例邮政编码(取自wikipedia page),并针对正则表达式测试每个邮政编码:

post_codes = ["M1 1AA", "M60 1NW", "CR2 6XH", "DN55 1PT", "W1A 1HQ", "EC1A 1BB", "bad one", "cc93h29r2"]
r = /^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? 1,2[0-9][ABD-HJLN-UW-Z]2|GIR 0AA)$/

post_codes.each do |pc|
  # pc =~ r will return something true if we have a match (specifically the integer of first match position)
  # We use !! to display it as true|false
  puts "#pc: #!!(pc =~ r)"
end
M1 1AA: true
M60 1NW: true
CR2 6XH: true
DN55 1PT: true
W1A 1HQ: true
EC1A 1BB: true
bad one: false
cc93h29r2: false

【讨论】:

数据库中的邮政编码是有效的,只是格式不正确。我需要重新格式化每个邮政编码并更新数据库。通常它们没有空格,大小写混合。以您的示例邮政编码集为例,我想将 dn551Pt 重新格式化为 DN55 1PT 并更新数据库中的条目。

以上是关于ruby 中的格式字符串(邮政编码)的主要内容,如果未能解决你的问题,请参考以下文章

Airbnb案例:Ruby on Rails YAML格式化字符串时导致的远程代码执行

如何使用 ruby​​ 1.9 转换字符编码

我可以在 Ruby 1.9 上设置默认字符串编码吗?

Ruby实例编程说明字符编码,解决乱码问题

Ruby to_json 出现错误“非法/格式错误的 utf-8”问题

使用 Ruby 查找给定编码字符串的组合