Jump to content

Need a bit of help from the regex wizards here


Go to solution Solved by Andreik,

Recommended Posts

for the life of me i never could figure out how to use regular expressions for string manipulation, so i'm going to need some help here.

i have an array with file names that have a date string like "2024", "202401" or "20240119" within them. for example:

  • \data\config6_202311_full.data
  • \data\config6_202312_full.data
  • \data\config5_202311_full.data
  • \data\config5_202312_full.data
  • \data\config7_202312_semi.data

now i need to filter through every file name in the array and get those date strings, because i need to manipulate and afterwards replace them. in the end, what i want to do is shift the selected files by a year, month or day. this solution doesnt have to use regex, but my best guess is that it's going to be.

Link to comment
Share on other sites

my graphics card died so i can't reply frequently. thanks for the question @andreik, i'll clarify:

  • if the file name has a four digit date string (so only the year), i'd like to extract exactly those four digits.
  • if the file name has a six digit date string (so year + month), i'd like to extract exactly those six digits.
  • if the file name has an eight digit date string (so year + month + day) i'd like to extract exactly those eight digits.

after extracting those strings i will shift the date one step earlier or later depending on user choice. so if the date was 2024, it would be 2023 if shifted to an earlier date. for 202202, we would go to 202201 in that case. this will be replaced in the file name and written back into the ui. after that, the user can write that config into the batch file which will be used by another tool to generate a new data report for the changed data files.

example:

  1. current string is "\data\config6_202311_full.data"
  2. $date = extract "202311" //regex god intervention required
  3. $newdate = shift_date($date) //which will be either "202310" or "202312"
  4. new string is stringreplace($currentstring, $date , $newdate)
Edited by Brobbl
Link to comment
Share on other sites

  • Solution

So this should work:

; Just year -> change up
Local $sExpr1 = '\data\config6_2023_full.data'
ConsoleWrite($sExpr1 & @TAB & ' --->>> ' & ProcessDate($sExpr1, True) & @CRLF)

; Year and month -> change down
Local $sExpr2 = '\data\config6_202305_full.data'
ConsoleWrite($sExpr2 & @TAB & ' --->>> ' & ProcessDate($sExpr2, False) & @CRLF)

; Year and month -> change up
Local $sExpr3 = '\data\config6_20230511_full.data'
ConsoleWrite($sExpr3 & @TAB & ' --->>> ' & ProcessDate($sExpr3, True) & @CRLF)

Func ProcessDate($sExpr, $bUp)
    Local $aRegEx = StringRegExp($sExpr, '^(?:.*?)(\d{4})(?:(\d{2}){0,1})(?:(\d{2}){0,1})(?:.*?)$', 3)
    If IsArray($aRegEx) Then
        Switch UBound($aRegEx)
            Case 1
                 Return String(Int($aRegEx[0]) + ($bUp ? 1 : -1))
            Case 2
                Return $aRegEx[0] & (StringLen(Int($aRegEx[1])) = 1 ? '0' : '') & String(Int($aRegEx[1]) + ($bUp ? 1 : -1))
            Case 3
                Return $aRegEx[0] & $aRegEx[1] & ((StringLen(Int($aRegEx[2])) = 1 ? '0' : '') & String(Int($aRegEx[2]) + ($bUp ? 1 : -1)))
        EndSwitch
    EndIf
EndFunc

You should be able to add a little bit more logic in this function for cases when month it's 12 and user want to go up so you don't result in invalid date. But this is beyond the scope since you are here for regex, right?

When the words fail... music speaks.

Link to comment
Share on other sites

Hi.

If you want to end up with valid datetime values, you will need to use _DateAdd() and figure out, wheather days, months or years need to be calculated.

 

; Year and month -> change down
Local $sExpr2 = '\data\config6_202301_full.data'
ConsoleWrite($sExpr2 & @TAB & ' --->>> ' & ProcessDate($sExpr2, False) & @CRLF)

; Year and month -> change up
Local $sExpr3 = '\data\config6_20230131_full.data'
ConsoleWrite($sExpr3 & @TAB & ' --->>> ' & ProcessDate($sExpr3, True) & @CRLF)

Func ProcessDate($sExpr, $bUp)
    Local $aRegEx = StringRegExp($sExpr, '^(?:.*?)(\d{4})(?:(\d{2}){0,1})(?:(\d{2}){0,1})(?:.*?)$', 3)
    If IsArray($aRegEx) Then
        Switch UBound($aRegEx)
            Case 1
                 Return String(Int($aRegEx[0]) + ($bUp ? 1 : -1))
            Case 2
                Return $aRegEx[0] & (StringLen(Int($aRegEx[1])) = 1 ? '0' : '') & String(Int($aRegEx[1]) + ($bUp ? 1 : -1))
            Case 3
                Return $aRegEx[0] & $aRegEx[1] & ((StringLen(Int($aRegEx[2])) = 1 ? '0' : '') & String(Int($aRegEx[2]) + ($bUp ? 1 : -1)))
        EndSwitch
    EndIf
EndFunc

 

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Link to comment
Share on other sites

This is awesome, thank you so much @andreik for even providing the algorythm to sort it out! Only just now got to read into your solution and it's so elegant. Not tested so far but i see what it does and I love it.

Date stuff was structured in my mind already, will be easy to case to the switch/case structure as I've been working with _dateadd() in the past. Kudos and many thanks again!! ❤️

Link to comment
Share on other sites

Actually awestruck about the Ternary expressions you used, didn't even know those were a thing, let alone in Autoit. Guess I'll finally upgrade from my 2012 version to up-to-date and work though all the code breaking changes... 🤪

Thanks for showing me.

Edited by Brobbl
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...