Regex 移动与给定正则表达式匹配的目录
我尝试移动目录及其内容。目录名称为字母加数字:Regex 移动与给定正则表达式匹配的目录,regex,powershell,Regex,Powershell,我尝试移动目录及其内容。目录名称为字母加数字: a2,a2321,sdadsa2321321,因此正则表达式应该是[a-zA-Z]+\d+。但是它不起作用 $SourceDirectoryPath = "C:/directory/[a-zA-Z]+\d+" $TargetFilePath = "C:/directory/target" New-Item -ItemType "directory" -Path $TargetFilePath Move-Item -Path $SourceDire
a2
,a2321
,sdadsa2321321
,因此正则表达式应该是[a-zA-Z]+\d+
。但是它不起作用
$SourceDirectoryPath = "C:/directory/[a-zA-Z]+\d+"
$TargetFilePath = "C:/directory/target"
New-Item -ItemType "directory" -Path $TargetFilePath
Move-Item -Path $SourceDirectoryPath -Destination $TargetFilePath -Force
如果我将[a-zA-Z]+\d+
替换为简单的通配符,如a*
它会移动多个目录,这证明[a-zA-Z]+\d+
是脚本中唯一不正确的部分
问题:在Powershell中正则表达式的正确形式是什么?这个正则表达式在Java中是完全正确的,但由于某些原因,它在这里不起作用。也许这就是您想要的:
$sourceDir = 'D:\source'
$destDir = 'D:\destination'
$pattern = '^.*[a-zA-Z]+\d+$'
$baseDir = Get-ChildItem -Path $sourceDir -Recurse -Directory
foreach( $directory in $baseDir ) {
if( $directory.Name -match $pattern ) {
Move-Item -Path $directory.FullName -Destination $destDir -Force
}
}
要在带有
Get ChildItem
的文件和文件夹上使用正则表达式匹配,需要使用Where Object
子句
这应该做到:
$SourceDirectoryPath = 'C:\directory'
$TargetFilePath = 'C:\directory\target'
# create the target path if it does not exist yet
if (!(Test-Path -Path $TargetFilePath -PathType Container)) {
$null = New-Item -Path $TargetFilePath -ItemType Directory
}
Get-ChildItem -Path $SourceDirectoryPath -Directory |
Where-Object { $_.Name -match '^[a-z]+\d+$' } |
ForEach-Object { $_ | Move-Item -Destination $TargetFilePath -Force }
如果我将[a-zA-Z]+\d+
替换为简单的通配符,如a*
它会移动多个目录,这证明[a-zA-Z]+\d+
是脚本中唯一不正确的部分
实际上:文件相关cmdlet的-Path
参数只能接受通配符表达式(请参阅),而不能接受正则表达式(regex)(请参阅)
- 这两种类型的表达式虽然有着远近的联系,但在语法上是不同的:通配符表达式在概念上和语法上都比较简单,但功能远不如通配符表达式强大,而且对于您的用例来说还不够强大。请参阅“对问题的评论”以获取快速介绍
- 还请注意,许多PowerShell cmdlet还方便地接受其他类型参数(与文件系统无关)中的通配符,例如
,允许您查找名称包含单词Get Command*job*
的所有可用命令job
-match
和-replace
之类的操作符、诸如Select String
之类的cmdlet,或带有-Regex
选项的开关
语句
在您的情况下,您需要通过将cmdlet与-match
组合,从所有子目录中筛选感兴趣的目录;语法上最简单的形式是使用操作语句(传递脚本块{…}
的一种更简洁的替代方法,其中必须使用$\uu
来引用手头的输入对象),如以下命令所示:
# Define the *parent* path of the dirs. to move.
# The actual dirs. must be filtered by regex below.
$SourceDirectoryParentPath = 'C:/directory'
$TargetFilePath = 'C:/directory/target'
# Note: If you add -Force, no error occurs if the directory already exists.
# New-Item produces output, a System.IO.DirectoryInfo in this case.
# To suppress the output, use: $null = New-Item ...
New-Item -ItemType "directory" -Path $TargetFilePath
# Enumerate the child directories of the parent path,
# and filter by whether each child directory's name matches the regex.
Get-ChildItem -Directory $SourceDirectoryParentPath |
Where-Object Name -match '^[a-z]+\d+$' |
Move-Item -Destination $TargetFilePath -Force
请注意,我已将regex[a-zA-Z]+\d+
更改为^[a-Z]+\d+$
,因为:
- PowerShell的正则表达式匹配默认情况下不区分大小写,因此
包含大写和小写(英文)字母[a-z]
运算符执行子字符串匹配,因此您需要使用-match
(开始时匹配)和结尾处的^
匹配来锚定正则表达式,以确保整个输入字符串与表达式匹配$
还请注意,我使用了单引号字符串(
“…”
)而不是双引号字符串(“…”
),这对于正则表达式文本更为可取,这样就不会在正则表达式引擎看到的字符和PowerShell本身可以预先插入的字符之间产生混淆,值得注意的是,$
和`
这*
不是指任何字符长度大于0的字符串吗?为什么这么重要?我总是使用托盘匹配整个表达式以避免副作用。-Path
使用通配符而不是正则表达式[a-z]
可以用作通配符范围,这意味着任何字符a-z
或a-z
,并且匹配的字符没有量词。因此[a-z][0-9]
将匹配a9
和B8
,但不匹配aa7
或Z10
<代码>?可以一次表示任何字符<代码>*是0个或更多不必匹配的字符。因此[a-z][0-9]*
将匹配a9
或b6544
或c4cdder32443
。