bash正则表达式将匹配YYMMDD但不是更长的数字

时间:2017-06-28 21:33:51

标签: regex bash macos

一般问题

我正在努力了解在编写正则表达式时如何防止在寻找模式之前或之后存在某些模式!

更具体的例子

我正在寻找一个正则表达式,它将匹配长字符串中YYMMDD((([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])))格式的日期,同时忽略更长的数字序列

它应该能够匹配:

  • text151124moretext
  • 123text151124moretext
  • text151124
  • text151124moretext1944
  • 151124

忽略

  • text15112412moretext (原因:它有8个数字而不是6个)
  • 151324 (原因:它不是有效的日期YYMMDD - 没有第13个月)

如果一个数字比这6个数字更多,我怎么能确保它不会在一个正则表达式中被选为日期(意思是,我宁愿避免预处理字符串) 我曾想过\D((19|20)([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1]))\D,但这是不是意味着必须某个角色之前和之后?

我正在使用bash 3.2(ERE)

谢谢!

3 个答案:

答案 0 :(得分:1)

尝试:

#!/usr/bin/env bash

extract_date() {
    local string="$1"
    local _date=`echo "$string" | sed -E 's/.*[^0-9]([0-9]{6})[^0-9].*/\1/'`
    #date -d $_date &> /dev/null # for Linux
    date -jf '%y%m%d' $_date &> /dev/null # for MacOS
    if [ $? -eq 0 ]; then
        echo $_date
    else
        return 1
    fi
}


extract_date text15111224moretext # ignore n_digits > 6
extract_date text151125moretext # take
extract_date text151132 # # ignore day 32
extract_date text151324moretext1944 # ignore month 13
extract_date text150931moretext1944 # ignore 31 Sept
extract_date 151126 # take

输出:

151125
151126

答案 1 :(得分:0)

如果您的令牌是行分隔的(即每行只有一个令牌):

^[\D]*[\d]{6}([\D]*|[\D]+[\d]{1,6})$

基本上,这个正则表达式代表:

  • 字符串开头的任意数量的非数字;
  • 正好6位数
  • 任意数量的非数字直到结尾或至少一个非数字和至少一个数字(最多6个)到字符串的结尾

此正则表达式传递了所有给定的样本输入。

答案 2 :(得分:0)

您可以使用非捕获组在日期正则表达式的任一侧定义非数字。我成功使用了这个表达式和相同的测试数据。

(?:\D)([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])(?:\D)