Exclude parameters taken from XML by regular expression (regex) - powershell

I have a parameter in XML files with a mask:
<id>ALL2-20210301-XXXXXX-XXXXX_X</id>
where ALL2 is always the same parameter, 20210301 is a date so changing every day, and XXXXXX-XXXXX_X is a variable parameter.
I want to parse XML and get 20210304 value (or other date) with regex - I don't need any other parameter from . How should regular expression value looks like?
code is:
[xml]$xml = Get-Content c:\buy\buy.xml
$date= $xml.buy.id[0]
if ($date -match "regex?") {
$date = $matches[0];
}

You don't need regex, you can just split on '-' and take the second element, so for example:
$result = ($date -split '-')[1]
It is likely faster than regex too (haven't measured).

Several alternative approaches
$date = 'ALL2-20210301-XXXXXX-XXXXX_X'
$date.Split('-')[1]
$date -split '-' | Select-Object -Index 1
$date -replace '^.+?-|-.+$'
$date -replace '.+(\d{8}).+','$1'
[regex]::Match($date,'\d{8}').Value
if($date -match '\d{8}'){$matches.0}

Related

Powershell Select-String

I need your help with PowerShell.
I need Select-String with fixed Date (in variable). & Set-Content to result.txt
Example: $Date = "01.07.2020"
But also i need select string with date which lower than i written in variable.
My code: Get-Content -Path log.txt | Select-String "?????" | Set-Content $result.txt
In log.txt i have many strings like " Creation date 01.07.2020 " ; " Creation date 01.06.2020 "
123.txt
Creation date 01.07.2020
Creation date 02.05.2020
Creation date 01.06.2020
Creation date 28.08.2020
Example script
$file = "C:\Users\userprofile\Desktop\test\123.txt"
$regexpattern = "\d{2}\.\d{2}\.\d{4}"
$content = Get-Content $file | Where-object { $_ -match $regexpattern}
foreach($line in $content){
$line.Substring(13,11)
}
I used regex to find the lines you are wanting to output. We get the content only if it matches our regex, then for each line we found, I'm using substring to pull the date out. You could also put together a regex for this if you wanted to. Since we know the lines have the same number of characters it's safe to use the substring function.
If you want that output to a file, simply find $line.Substring(13,11) and then add this after it | Out-file "C:\Users\userprofile\desktop\test\output.txt" -append.

Finding value in a CSV file and comparing with today's date

I'm trying to get a value from a CSV file.
If today's date = DateInCSVFile give the "key" value.
Keys.csv
Guest,Key
1-Jun,OIOMY-ZFILZ
2-Jun,LSSJC-PDEUL
3-Jun,MQNVJ-TETLV
4-Jun,HCJIJ-ECVPY
5-Jun,SPACR-AJSLU
6-Jun,MEURS-UQTVX
Code:
$today = Get-Date -format dd-MMM
$keys = import-csv c:\office\keys.csv -Header #(1..2)
$data = $keys | ? { $_.1 -match $today}
Write-Host $data.2
I tried the foreach and if commands. Nothing worked.
I can think of a couple of options. If you want something quick and dirty, try:
$stuff = Import-Csv -Path .\stuff.csv
foreach ($thing in $stuff) {
if ( $thing.Guest -eq $(Get-date -Format 'd-MMM') ) {
Write-Output $thing.Key
}
}
I import the CSV file's contents to a variable. I iterate over each line. If the day in Guest matches the current day, I output the key
The only problem with your code is your date format, dd-MMM, as LotPings observes:
It creates 0-left-padded numbers for single-digit days such as 6, whereas the dates in the CSV have no such padding.
Thus, changing Get-Date -format dd-MMM to Get-Date -format d-MMM (just d instead of dd) should fix your problem.
However, given that you're reading the entire file into memory anyway, you can optimize the command to (PSv4+):
$today = Get-Date -Format d-MMM
(Import-Csv c:\office\keys.csv).Where({ $_.Guest -eq $today }).Key
Also note that the purpose of -match is to perform regular-expression-based matching, not (case-insensitive) string equality; use -eq for the latter.

Powershell change date format based on regex

I am trying to use a regex to find dates in a csv file and change the formatting because there are over 200 columns in this csv; manual column mapping for each date is not possible.
what I had previously was the following
$sf = '\\path\dept\Extracts\Date_Modified.csv'
$regex = "\d{1,2}/\d{1,2}/\d{4}"
(Get-Content $sf) |
Foreach-Object {$_ -replace $regex, (get-date -f "yyyy-MM-dd") } |
Set-Content $sf
that works fine if I want to replace all the dates with the current date, but that wasn't my goal. my goal is to recognize human entry type dates (mm/dd/yyyy) and change them to yyyy-mm-dd that the database table is expecting when I load the csv.
how can I modify this? or is there a better way to recognize date formats and change the format?
The answer: use capture groups. I don't know why you wouldn't be able to assign the regex to a variable before use (as I have done many times):
$sf = '\\path\dept\Extracts\Date_Modified.csv'
$regex = '(\d{1,2})\/(\d{1,2})\/(\d{4})'
#(Get-Content -Path $sf) |
ForEach-Object { $_ -replace $regex, '$3-$1-$2' } |
Set-Content -Path $sf
Of special note, use single-quotes in the replace statement so you don't end up trying to interpolate $1 into a (presumably null) variable.

Powershell replace operator is bringing across array artifacts

I need to get a date from a cell in a CSV file, then remove the '20' from the year.
I have the below code:
$rateID="C:\Folder\Path\RateIDTable.csv"
$date = Import-CSV $rateid | select -first 1 -Property date
$date = $date -replace '[20]',''
write-output $date
Output looks like this though:
What I need is '17/01/18' but it adds the whole variable and removes the zero that I need.
Any tips on this one?
Thanks!
Either you convert the "string date" to a datetime object and format it accordingly or you change the regex pattern you use in your -replace operator like this
$date = $date -replace '/20','/'
The square brackets in regex define a charachter class. So with '[20]' the regex matches ALL two's and ALL zero's in the string.
OK, figured it out. bit of a messy way to do it, but here is my code:
$rateID="C:\Folder\Path\RateIDTable.csv"
$datestr="C:\folder\path\fdate.txt"
$date = Import-CSV $rateid | select -first 1 -Property date
$fdate = $date | foreach-object {$_.date} | set-content $datestr
$fdate = (get-content $datestr) -replace ('20','')
write-output $fdate
And my output is this:
17/01/18
Thanks to all those who helped!
Once you have your $date object, format it as such:
$date = $date.ToString("dd/MM/yy")
Adding more clarification since my answer did not seem to work for you. I assumed a few things, that I can see did not work for you.
$date1 = [datetime]::Now
$date2 = [datetime]::Parse("01/18/2018")
$mydate = "01/19/2018"
$date3 = [datetime]::Parse($mydate)
$date1.ToString("dd/MM/yy")
$date2.ToString("dd/MM/yy")
$date3.ToString("dd/MM/yy")
Your $date was a string, not a Date, so yes, to use ToString, it would need to be a DateTime object which you can see a few ways to create above. Hope this helps you in future efforts.
Note, you may need to change the strings depending on your locale so they parse correctly, but hopefully the above makes sense...

Remove attribute and reformat date string in a file

I'm able to remove the attribute using the codes below. However, I don't know how to reformat a date string to the ISO format. From date="20140424T140222Z" to date="2014-04-24T14:02:22Z"
function update {
$unzippedLocation = Get-ChildItem $destination -Recurse
# from date="20140424T140222Z" to date="2014-04-24T14:02:22Z"
Message "Remove and reformat attributes"
$regex='date="(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z"'
ForEach($unzippedFile in $unzippedLocation) {
(Get-Content $unzippedFile) |
ForEach-Object { $_ -replace ' crc=""', '' } |
ForEach-Object { $_ -replace $regex, 'date="$1-$2-$3T$4:$5:$6Z"' } |
Set-Content $unzippedFile
Write-Host "crc attribute has been removed from $($unzippedFile.Name)"
Write-Host "date attribute has been reformated from $($unzippedFile.Name)"
}
}
I don't fully understand where you need to that the replacement of the date, but one approach is to use regular expression to update the date. Here is a sample for one string, you can incorporate it where you need to:
#Defines regex with a separate group for each component
$regex='date="(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z"'
#Sample input
$input = 'date="20140424T140222Z"'
#Update the string
$result = $input -replace $regex, 'date="$1-$2-$3T$4:$5:$6Z"'
Write-Host $result
#Result is
#date="2014-04-24T14:02:22Z"
You can use the .net method TryParseExact.
This method will try to parse any string in a valid DateTime value and then you format back to ISO format. Using this method you test if your values are valid.
Example:
$dateString = "20140424T140222Z"
$format = "yyyyMMddTHHmmssZ"
[ref]$parsedDate = get-date
$parsed = [DateTime]::TryParseExact($dateString, $format,[System.Globalization.CultureInfo]::InvariantCulture,[System.Globalization.DateTimeStyles]::None,$parseddate)
if($parsed)
{
write "$dateString is valid"
}
$parseddate.Value.ToString("yyyy-MM-ddTHH:mm:ssZ")