regex 正则表达式不能是管道的第一个元素-如何获得匹配

p4rjhz4m  于 2023-02-05  发布在  其他
关注(0)|答案(2)|浏览(106)

我有一个在Windows 10命令行运行的正则表达式,并得到错误:

Expressions are only allowed as the first element of a pipeline.

我不知道如何把它和第一个元素中的match部分放在一起。
这是文件内容(显示了重要部件......有多个制造商和序列号,但我只需要具体的一个):
电子邮件:\临时\详细信息.txt:

...
  Manufacturer: SGSS
  S/N: A791D734804

...

我用这个powershell成功地从文档中获取了上面的两行代码,但是我在提取分号后面的序列号时遇到了麻烦。
这可以提取制造商和序列号行(上下文部分也会在模式匹配后获得行):

powershell "Get-Content e:\temp\details.txt | select-String -Pattern SGSS -Context 0,1"

然而,我尝试只返回序列号(),并得到上面的错误,这就是我在match/命令中得到错误的地方:

powershell "Get-Content -Raw e:\temp\details.txt | select-String -Pattern SGSS -Context 0,1 | $_ -match '(?ms)(N:\s)(([a-zA-Z0-9])+)'"

我测试了正则表达式在regex测试器中的工作情况:

(N:\s)(([a-zA-Z0-9])+)

我使用了这个example for the match,但是我不能把它放在表达式的第一位(就像示例一样),因为我正在做其他事情。

**更新:**示例文档内容:

A00232473244B

USB xController
RootHub
Port[6] USB Reader
Manufacturer: Gen 
S/N: 0A0000002071


Intel(R) 8 Series/1234 Series 
RootHub
Port[1]Standard-USB-Hub

USB x Controller
RootHub
Port[1] abc Printer
Manufacturer: guess
S/N: A2622431

Port[2] SG
Manufacturer: SGSS
S/N: A791B634801

更新2:

我在regex测试器中尝试了这个regex,它仍然只找到了第一个S/N行,而不是下面的行,或者只是我关心的SGSS行:

S\/N:\s([a-zA-Z0-9]+)[\n\r\S\s]*

**Update 3:**我尝试的一些操作没有返回任何内容:

powershell -command Get-Content e:\temp\details.txt -Raw ^| Where{$_ -match '(?ms)SGSS[\r\n\s]*S\/N: (\S+)\b'} ^| ForEach-Object { $Matches[1]}

powershell -command Get-Content e:\temp\details.txt -Raw ^| Where{$_ -match '(?ms)SGSS[\r\n\s]*S\/N: (\S+)\b'} ^| ForEach-Object { echo $Matches[1]}

powershell -command Get-Content e:\temp\details.txt -Raw ^| Where{$_ -match '(?ms)SGSS[\n\r]S\/N:\s([\w]*)'} ^| ForEach-Object { echo $Matches[1]}

powershell -command Get-Content e:\temp\details.txt -Raw ^| select-string -Pattern 'SGSS[\n\r]S\/N:\s([\w]*)' ^| ForEach-Object { echo $Matches[1]}

powershell -command Get-Content e:\temp\devices.txt -Raw ^| Where{$_ -match '(?ms)SGSS[\r\n\s]*S/N: (\S+)\b'} ^| ForEach-Object { $Matches[1]}

更新4:

我试过了,它仍然没有返回任何东西,也没有错误。可能是换行符/空格的问题。我不确定。
powershell -获取内容命令“e:\temp\details.txt”^|Foreach对象{如果($_ -匹配“SGSS”){$Found=1};如果(($_ -匹配“序列号:\s([a-zA-Z 0 -9]+)[\n\r\S\s]*”)-和($Found -等式1)){$_ -替换“^.*N:\s”}}

更新5:

我尝试在我们的设备(Windows 10)的命令行中测试它,并尝试将其放入ps1文件中运行。我遇到错误或没有任何问题(在命令行中使用c:\temp〉powershell ./SG_SN.ps1运行):

powershell "Get-Content e:\temp\details.txt -Raw | select-String -Pattern 'SGSS[\n\r]S\/N:\s([\w]*)'  | ForEach-Object {echo $Matches[1]}"

结果:没有返回任何内容,没有错误

powershell "Get-Content e:\temp\usbconnecteddevices.txt -Raw ^| select-String -Pattern 'SAWGRASS[\n\r]S\/N:\s([\w]*)'  ^| ForEach-Object {echo $Matches[1]}"

结果:错误:

Get-Content : A positional parameter cannot be found that accepts argument '^'.
At line:1 char:1
+ Get-Content e:\temp\details.txt -Raw ^| select-String -Pa ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

注意,我不想在powershell伊势或PS提示符下测试它,因为我们最终无法以这种方式运行它。

**Update 6:**这似乎是在PowershellISE工作。我将在命令行测试它。它是基于一些从我的笔记过去一年或更多。

Get-Content 'e:\temp\details.txt' | select-String -Pattern SGSS -Context 0,1 |
ForEach-Object -Process { $result = $_ -split ':'; echo 'here';$result[-1]}
a8jjtwal

a8jjtwal1#

您可以在ForEach-Object脚本块中使用Where-Object和自动$Matches变量来获得所需的内容:

powershell -command Get-Content e:\temp\details.txt -raw ^| Where{$_ -match '(?ms)SGSS[\r\n\s]*S/N: (\S+)\b'} ^| ForEach-Object {$Matches[1]}

更新以避开管道并修复报价问题。

42fyovps

42fyovps2#

也许您可以尝试设置一个标志变量,然后在下一个匹配的模式上执行操作。这是针对上面的details.txt示例的测试文件进行的测试。它正确地选择了您的SGSS S/N #。我确实稍微修改了它,以便在成功匹配"SGSS"时,它只删除"S/N:"文本。
这是多行格式,如果你用单行格式,我想你需要在ForEach-Object块中加上分号。

powershell -Command Get-Content 'e:\temp\details.txt' | 
    Foreach-Object {
        if($_ -match 'SGSS') { $Found = 1 };
        if(($_ -match 'S\/N:\s([a-zA-Z0-9]+)[\n\r\S\s]*') -and ($Found -eq 1)) { $_ -replace '^.*N:\s' }
    }

和单层内衬:

powershell -Command Get-Content 'e:\temp\details.txt' ^| Foreach-Object { if($_ -match 'SGSS') { $Found = 1 }; if(($_ -match 'S\/N:\s([a-zA-Z0-9]+)[\n\r\S\s]*') -and ($Found -eq 1)) { $_ -replace '^.*N:\s' } }
    • EDIT:**看起来您最幸运的是将整个PowerShell命令封装在双引号中。这似乎更像是将整个命令字符串传递给powershell而不是没有正确的powershell命令来检索数据的问题。如果像下面这样封装,上面的命令可能会在您的特定设备接口上运行。
powershell "Get-Content 'e:\temp\details.txt' | Foreach-Object { if($_ -match 'SGSS') { $Found = 1 }; if(($_ -match 'S\/N:\s([a-zA-Z0-9]+)[\n\r\S\s]*') -and ($Found -eq 1)) { $_ -replace '^.*N:\s' } }"

这在cmd.exe上成功运行并检索到S/N #,但我不能说它是否会在您的设备接口上运行。
此外,使用添加了"ForEach-Object"和匹配结果表达式($Matches [2])的原始命令,我收到了相同的结果。我相信您最初收到的错误是在Foreach-Object块外部表达$_的结果。

powershell "Get-Content e:\temp\details.txt | select-String -Pattern SGSS -Context 0,1 | ForEach-Object { $_ -match '(?ms)(N:\s)(([a-zA-Z0-9])+)'; $Matches[2] }"

结果

True
A791B634801

可通过调整此处删除"True"输出...{$-match 'regex'|超出空值; $匹配[2 ]}
至于您最初的错误,我相信您是通过管道连接到变量($
),这是一个表达式赋值操作,如下例所示。

"THIS IS A TEST STRING PIPED TO A VARIABLE" | $TEST

    At line:1 char:49
Expressions are only allowed as the first element of a pipeline.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ExpressionsMustBeFirstInPipeline
    
$TEST = "THIS IS A TEST STRING PIPED TO A VARIABLE" | ForEach-Object { $_ }

No Error

相关问题