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