从字符串中提取每个唯一数据

时间:2015-07-01 16:51:05

标签: regex

我一直试图为以下内容设置REGEX提取过程无济于事。

我有一组日期值,格式如下。我需要能够将这些提取为独特的个人日期。

如果有单个值,则为mm / dd / yyyy的标准简单格式。那个很容易。

如果有多个日期值,则可以采用以下格式: 2016年2月5日,12日,19日,26日,2016年3月4日

我需要将这些转变为2016年5月2日,2016年12月2日等。

最终我将这些日期插入数据库。

我是以错误的方式解决这个问题吗?谢谢你的建议。

2 个答案:

答案 0 :(得分:1)

如果您尝试使用一个正则表达式,这将是完整的意大利面条:

  • 您必须对月份的名称和相应的数字进行硬编码。
  • 这一年的日期列表之后,而不是在所有月份名称列表 - 今年的月份日之后,年份不会跟进。

然而,在普通编程语言的帮助下,您仍然可以获得简短且以正则表达式为中心的解决方案。这是一个小的Ruby片段,用于显示一般概念:

# this is the input
dates = "Feb 5, 12, 19, 26, Mar 4, 11 2016, Jul 5, 7, 19, 26, May 4, 11 2017"

# a hash with month name => month number
MONTHS = {
  'Jan' => '01',
  'Feb' => '02',
  'Mar' => '03',
  'Apr' => '04',
  'May' => '05',
  'Jun' => '06',
  'Jul' => '07',
  'Aug' => '08',
  'Sep' => '09',
  'Oct' => '10',
  'Nov' => '11',
  'Dec' => '12',
}

# match and extract three things:
#  month - the first found month name (three letters)
#  days  - list of days separated by commas and spaces for this month
#           for example 5, 12, 19, 26, 
#  year  - the first found year (four digits)
# ,? is because we don't have , after the last day of the year
while dates =~ /(\w{3}) ((?:\d\d?,? )+).*?(\d{4})/
  month, days, year = $1, $2, $3
  # to each day collate a date in the wanted format
  #  MONTHS[month] gets the month number from the hash above
  #  sprintf simply makes sure that one digit days will have a leading 0
  dates_this_month = days.split(/,? /).map do |day|
    "#{MONTHS[month]}/#{sprintf('%02d', day)}/#{year}"
  end.join ', '
  # substitute the dates for this month with the new format
  dates.sub! "#{month} #{days}", "#{dates_this_month}, "
end

# remove leftover years
dates.gsub! /, \d{4}/, ''

现在dates处于所需的格式。

答案 1 :(得分:0)

假设您正在RegExing的数据中没有偏差或异常,可以应用以下RegEx并设置区分大小写,并允许您访问所需的信息。使用RegExs,“了解您的数据”非常重要,因为这个变量可以极大地改变RegEx的结构 - 特异性和清晰度之间的平衡非常重要,因为RegEx很容易变得笨拙和神秘。

将月份保存为:([A-Z][a-z][a-z]) //这可以是您的$ 1变量(稍后有用)

将日期值保存为:\s*(?:([0-9]?[0-9]),\s)* // $ 2变量应该可用于访问此值列表

将年份值保存为:([0-9]{4,4}) // $ 3变量应该可用于访问这些值注意:这仅适用于####格式化日期的设计,尽管可以更改它以处理不同的格式;我刚刚结束你提供的例子

将它们串在一起得到:(?:([A-Z][a-z][a-z])\s*(?:([0-9]?[0-9]),\s)*)+([0-9]{4,4})

然后,您可以使用这些值构造对象,这样您就不会得到一堆混乱的数据。如果我正确地解决了您的问题,请告诉我。如果我遗漏了某些内容或者您忘记提及的其他功能,我将非常乐意为您提供协助。