英文:
powershell "-match" not matching as hoped, seeking advice
问题
以下是修复的匹配字符串,以及原因:
$fileName = "Youghusband Friends 2012-12-14 003.jpg"
if ($fileName -match '(\d{1,2}|\d{2})[-_.](\d{1,2}|\d{2})[-_.](\d{4}).*') {
$matchedPart = $matches[0]
Write-Host "FILE_MATCH_C (c) ALL: '$fileName' Matched Part: '$matchedPart' matches[1..3]='${matches[1]}-${matches[2]}-${matches[3]}'"
} elseif ($fileName -match '(\d{4})[-_.](\d{1,2}|\d{2})[-_.](\d{1,2}|\d{2}).*') {
$matchedPart = $matches[0]
Write-Host "FILE_MATCH_D (d) ALL: '$fileName' Matched Part: '$matchedPart' matches[1..3]='${matches[1]}-${matches[2]}-${matches[3]}'"
} else {
Write-Host "FILE_NO_MATCH: '$fileName'"
}
修复的匹配字符串主要改变了正则表达式中的模式。现在,匹配字符串不再包括字符串的开头和结束的锚点(^
和$
),因此可以匹配日期字符串出现在文件名中的任何位置。此外,我们还将匹配后面的任意字符((.*)
)移到了正则表达式之外。
希望这能解决你的问题。
英文:
I have a need to rename files and folders based on a date anywhere in the name/folder string, front/middle/end.
The date formats can be like:
- DD-MM-YYYY
- D-M-YYYY
- D-MM-YYYY
- DD-M-YYYY
- YYYY-MM-DD
- YYYY-M-D
- YYYY-MM-D
- YYYY-M-DD
and intra-date separators can be any of these 3 characters
- - (dash)
- _ (underscore)
- . (period)
I had thought the match strings below (provided by ChatGPT) would do the trick but no.
It only matches if the date is at the start of a string.
$fileName = "Youghusband Friends 2012-12-14 003.jpg"
if ($fileName -match '^(\d{1,2}|\d{2})[-_.](\d{1,2}|\d{2})[-_.](\d{4})(.*)$') {
$matchedPart = $matches[0]
Write-Host "FILE_MATCH_C (c) ALL: '$fileName' Matched Part: '$matchedPart' matches[1..3]='$matches[1..3]'"
} elseif ($fileName -match '^(\d{4})[-_.](\d{1,2}|\d{2})[-_.](\d{1,2}|\d{2})(.*)$') {
$matchedPart = $matches[0]
Write-Host "FILE_MATCH_D (d) ALL: '$fileName' Matched Part: '$matchedPart' matches[1..3]='$matches[1..3]'"
} else {
Write-Host "FILE_NO_MATCH: '$fileName'"
}
Result:
FILE_NO_MATCH: 'Youghusband Friends 2012-12-14 003.jpg'
What match strings would fix it ? (and why)
Thanks
答案1
得分: 3
你的正则表达式存在问题,主要是使用了 ^
(行的开头)和 $
(行的结尾),而不是使用单词边界(\b
)。以下是如何使用单个正则表达式来处理你的代码的方式:
$re = '(?x)
\b(?:
(?<day>[0-9]{1,2})[-_.]
(?<month>[0-9]{1,2})[-_.]
(?<year>[0-9]{4})
|
(?<year>[0-9]{4})[-_.]
(?<month>[0-9]{1,2})[-_.]
(?<day>[0-9]{1,2})
)\b'
$fileName = 'Youghusband Friends 2012-12-14 003.jpg'
if ($fileName -match $re) {
# 如果你想将其作为日期时间实例,你可以这样做:
# [datetime]::new($Matches['year'], $Matches['month'], $Matches['day'])
[pscustomobject]@{
date = $Matches[0]
year = $Matches['year']
month = $Matches['month']
day = $Matches['day']
}
}
else {
Write-Host "FILE_NO_MATCH: '$fileName'"
}
有关正则表达式详细信息,请参见 https://regex101.com/r/R0EkUj/1。
英文:
The clear issue with your regex is the use of ^
(start of the line) and $
(end of the line) instead of using word boundaries (\b
). Here is how you could approach your code with a single regex:
$re = '(?x)
\b(?:
(?<day>[0-9]{1,2})[-_.]
(?<month>[0-9]{1,2})[-_.]
(?<year>[0-9]{4})
|
(?<year>[0-9]{4})[-_.]
(?<month>[0-9]{1,2})[-_.]
(?<day>[0-9]{1,2})
)\b'
$fileName = 'Youghusband Friends 2012-12-14 003.jpg'
if ($fileName -match $re) {
# if you want to have it as a datetime instace, here you can do:
# [datetime]::new($Matches['year'], $Matches['month'], $Matches['day'])
[pscustomobject]@{
date = $Matches[0]
year = $Matches['year']
month = $Matches['month']
day = $Matches['day']
}
}
else {
Write-Host "FILE_NO_MATCH: '$fileName'"
}
See https://regex101.com/r/R0EkUj/1 for regex details.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论