复杂的正则表达式 - 在Powershell中工作,而不是在Bash中工作

问题描述 投票:1回答:3

下面的代码是我的代码的一小部分,用于解析Netbackup命令的输出。这适用于我们的Windows机箱,但我们的一些机箱是RHEL。

我正在尝试将下面的代码转换为RHEL 4.X上可用的东西,但我正在解析正则表达式。显然下面的代码有一些转义为与Powershell一起使用的字符,我没有将这些字符用于Shell。

我还不熟悉Shell,但我会在Powershell代码下面发布一部分Shell代码。

$output = ./bpdbjobs

$Results = @()
$ColumnName = @()

foreach ($match in $OUTPUT) {
   $matches = $null
   $match -match "(?<jobID>\d+)?\s+(?<Type>(\b[^\d\W]+\b)|(\b[^\d\W]+\b\s+\b[^\d\W]+\b))?\s+(?<State>(Done)|(Active)|(\w+`-\w+`-\w+))?\s+(?<Status>\d+)?\s+(?<Policy>(\w+)|(\w+`_\w+)|(\w+`_\w+`_\w+))?\s+(?<Schedule>(\b[^\d\W]+\b\-\b[^\d\W]+\b)|(\-)|(\b[^\d\W]+\b))?\s+(?<Client>(\w+\.\w+\.\w+)|(\w+))?\s+(?<Dest_Media_Svr>(\w+\.\w+\.\w+)|(\w+))?\s+(?<Active_PID>\d+)?\s+(?<FATPipe>\b[^\d\W]+\b)?"
   $Results+=$matches
   }

下面是我编写的Shell代码的一小部分(这显然是非常错误的,我在这里学习)。我只是用它来测试Regex,看看它是否在Shell中运行 - (Spoiler alert)它没有。

#!/bin/bash
#

backups=bpdbjobs
results=()

for results in $backups; do

    [[ $results =~ /(?<jobID>\d+)?\s+(?<Type>(\b[^\d\W]+\b)|(\b[^\d\W]+\b\s+\b[^\d\W]+\b))?\s+(?<State>(Done)|(Active)|(\w+\w+\-\w\-+))?\s+(?<Status>\d+)?\s+(?<Policy>(\w+)|(\w+\_\w+)|(\w+\_\w+\_\w+))?\s+(?<Schedule>(\b[^\d\W]+\b\-\b[^\d\W]+\b)|(\-)|(\b[^\d\W]+\b))?\s+(?<Client>(\w+\.\w+\.\w+)|(\w+))?\s+(?<Dest_Media_Svr>(\w+\.\w+\.\w+)|(\w+))?\s+(?<Active_PID>\d+)?/ ]]

done

$results

以下是我得到的错误。

 ./netbackupsolarwinds.sh: line 9: syntax error in conditional expression: unexpected token `('
 ./netbackupsolarwinds.sh: line 9: syntax error near `/(?'
 ./netbackupsolarwinds.sh: line 9: `        [[ $results =~ /(?<jobID>\d+)?\s+(?<Type>(\b[^\d\W]+\b)|(\b[^\d\W]+\b\s+\b[^\d\W]+\b))?\s+(?<State>(Done)|(Active)|(\w+\w+\-\w\-+))?\s+(?<Status>\d+)?\s+(?<Policy>(\w+)|(\w+\_\w+)|(\w+\_\w+\_\w+))?\s+(?<Schedule>(\b[^\d\W]+\b\-\b[^\d\W]+\b)|(\-)|(\b[^\d\W]+\b))?\s+(?<Client>(\w+\.\w+\.\w+)|(\w+))?\s+(?<Dest_Media_Svr>(\w+\.\w+\.\w+)|(\w+))?\s+(?<Active_PID>\d+)?/ ]]'
regex bash shell powershell
3个回答
0
投票

来自man bash

可以使用另一个二元运算符=〜,其优先级与==和!=相同。使用它时,操作符右侧的字符串被视为扩展正则表达式并相应地匹配(如regex(3)中所示)。

这意味着表达式被解析为POSIX扩展正则表达式,AFAIK不支持命名捕获组((?<name>...))或字符转义(\d\w\s,...)。

如果你想使用[[ $var =~ expr ]],你需要重写正则表达式。否则使用grep(支持PCRE):

grep -P '(?<jobID>\d+)?\s+...' <<<$results

0
投票

更新后的答案,更新后的答案。

快速执行迁移的最佳方法是使用Grep的--perl-regexp Perl兼容性选项,如最终在另一个答案中建议的那样。

如果您仍想使用纯Bash执行此操作,则需要在the documentation之后相应地重写正则表达式。


0
投票

谢谢大家的答案。我交换到Grep -P无济于事,原来命名的捕获组是Grep -P的问题。

我也无法找到一种方法来使用Grep将捕获组匹配输出到单个变量。

这导致我交换使用perl,如下所示,改变我的正则表达式。

bpdbjobs | perl -lne 'print "$1" if /(\d+)?\s+((\b[^\d\W]+\b)|(\b[^\d\W]+\b\s+\b[^\d\W]+\b))?\s+((Done)|(Active)|(\w+\w+\-\w\-+))?\s+(\d+)?\s+((\w+)|(\w+\_\w+)|(\w+\_\w+\_\w+))?\s+((b[^\d\W]+\b\-\b[^\d\W]+\b)|(\-)|(\b[^\d\W]+\b))?\s+((\w+\.\w+\.\w+)|(\w+))?\s+((\w+\.\w+\.\w+)|(\w+))?\s+(\d+)?/g'

$<num>指的是捕获组编号。我现在可以列出,显示和(重要部分)计算单个组内的匹配数,对应于每列中找到的数据。

© www.soinside.com 2019 - 2024. All rights reserved.