The general problem
===================

I am trying to understand how to prevent the existence of some pattern before or after a sought-out pattern when writing regex's!

A more specific example
=======================

I'm looking for a regex that will match dates in the format YYMMDD (`(([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1]))`) inside a long string while ignoring longer numeric sequences

it should be able to match:

* text151124moretext
* 123text151124moretext
* text151124
* text151124moretext1944
* 151124

but should **ignore**:

* text15112412moretext
(reason: it has 8 numbers instead of 6)
* 151324
(reason: it is not a valid date YYMMDD - there is no 13th month)

how can I make sure that if a number has **more** than these 6 digits, it won't picked up as a date inside one single regex (meaning, that I would rather avoid preprocessing the string)
I've thought of `\D((19|20)([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1]))\D` but doesn't this mean that there **has to be** some character before and after?

I'm using bash 3.2 (ERE)

thanks!
['https://Stackoverflow.com/questions/44812906', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/3017323/']
Try:

```
#!/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

```

Output:

```
151125
151126

```
If your tokens are line-separated (i.e. there is only one token per line):

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

```

Basically, this regex looks for:

* Any number of non-digits at the beginning of the string;
* Exactly 6 digits
* Any number of non-digits until the end OR at least one non-digit and at least one digit (up to 6) to the end of the string

This regex passes all of your given sample inputs.