转换为 Powershell

Converting to Powershell

我有这个 perl 代码,我正在尝试将其转换为 powershell。

foreach my $f ( @file_list ) {
    if( $f =~ /^([\d]+)_${base_ver}_([\d]{4})\.zip$/i ){
        $pfile = $f;
        ( $pnum, $pdate ) = ( $pfile =~ /^([\d]+)_${base_ver}_([\d]{4})\.zip$/i ); # need to convert
        ( $pmon, $pyear ) = ( $pdate =~ /^(\d\d)(\d\d)$/ ); # need to convert
        if( ($patch_nbr == 0) || ($patch_nbr == $pnum) ) {
            $fcnt++;
        }
    }
}

我在这里转换了大部分..

$file_list = Get-ChildItem -force $base_dir
$file_list | foreach-object {
    if($_ -match "/^([\d]+)_${base_ver}_([\d]{4})\.zip$/i"){
        $pfile = $_


        if($patch_nbr -eq 0 -or $pacth_nbr -eq $pnum){
            $fcnt++
        }
    }
}

不太确定如何转换等于正则表达式的两个变量,或者是否有比我已有的更好的方法将 perl 代码转换为 powershell。

perl 中的 [mode]/pattern/[replace/][options] 语法不适用于 PowerShell 中的正则表达式。

因此,你的模式

/^([\d]+)_${base_ver}_([\d]{4})\.zip$/i

变成

^([\d]+)_${base_ver}_([\d]{4})\.zip$

(i不需要,-match默认解析为-imatch(case-i不敏感匹配)


要捕获号码前缀和日期,您可以使用命名捕获组 ((?<name>pattern)):

^(?<num>[\d]+)_${base_ver}_(?<date>[\d]{4})\.zip$

然后您可以从 $Matches["name"]:

获取匹配项
if($f -match "^(?<num>[\d]+)_${base_ver}_(?<date>[\d]{4})\.zip$"){
    $pfile = $f
    $pnum = $Matches["num"]
    $pdate = $Matches["date"]
    $pmon = -join $pdate[0..1]
    $pyear = -join $pdate[2..3]
}

您还可以更改正则表达式模式以单独捕获月份和年份:

if($f -match "^(?<num>[\d]+)_${base_ver}_(?<month>[\d]{2})(?<year>[\d]{2})\.zip$"){
    $pfile = $f
    $pnum = $Matches["num"]
    $pmon = $Matches["month"]
    $pyear = $Matches["year"]
}

我会先放一个 Where-Object 过滤器。这允许您在随后的 ForEach-Object 中使用 $matches 集合,而无需在嵌套的 if 语句中使用第二个 -match。如果您还将日期模式从 (\d{4}) 更改为 (\d{2})(\d{2}),则可以在单个语句中分配 $pnum$pmon$pyear。您还可以简化递增 $fcnt 的条件。您可以检查它是否包含在两个值的数组中,而不是检查 $patch_nbr 是否等于两个值之一。

Get-ChildItem -Force $base_dir |
  Where-Object { $_ -match '^(\d+)_${base_ver}_(\d{2})(\d{2})\.zip$' } |
  ForEach-Object {
    $pnum, $pmon, $pyear = $matches[1..3]
    if (0, $pnum -contains $patch_nbr) { $fcnt++ }
  }
}

当然,如果您只想计算与给定补丁号匹配的文件数,您可以这样做:

$f = Get-ChildItem -Force $base_dir | Where-Object {
       $_ -match '^(\d+)_${base_ver}_\d{4}\.zip$' -and
       0, $matches[1] -contains $patch_nbr
     }
$fcnt = @($f).Count