Powershell,如何捕获 Select-String 的参数并包含匹配的输出
Powershell, how to capture argument(s) of Select-String and include with matched output
感谢@mklement0 帮助我们在 .
中给出答案
下面的 Powershell 可以很好地查找源代码文件夹中出现的一长串数据库字段名称。
$inputFile = 'C:\DataColumnsNames.txt'
$outputFile = 'C:\DataColumnsUsages.txt'
Get-ChildItem C:\ProjectFolder -Filter *.cs -Recurse -Force -ea SilentlyContinue |
Select-String -Pattern (Get-Content $inputFile) |
Select-Object Path, LineNumber, line |
Export-csv $outputfile
但是,很多行源代码有多个匹配项,尤其是ADO.NET SQL语句一行有很多字段名。如果字段名称参数包含在匹配输出中,则结果将更直接有用,而无需额外处理,例如将所有内容与原始字段名称列表对齐。例如,如果有源行“BatchId = NewId”,它将匹配字段名列表项“BatchId”。有没有一种简单的方法可以在输出中包含“BatchId”和“BatchId = NewId”?
玩过 matches 对象,但它似乎没有信息。也像这里一样尝试了管道变量,但 X 为空。
$inputFile = 'C:\DataColumnsNames.txt'
$outputFile = 'C:\DataColumnsUsages.txt'
Get-ChildItem C:\ProjectFolder -Filter *.cs -Recurse -Force -ea SilentlyContinue |
Select-String -Pattern (Get-Content $inputFile -PipelineVariable x) |
Select-Object $x, Path, LineNumber, line |
Export-csv $outputile
谢谢。
Microsoft.PowerShell.Commands.MatchInfo
instances that Select-String
输出有 a Pattern
属性 反映了(潜在)array 中的特定模式在给定行 .
上传递给 -Pattern
并匹配 的模式数
警告是如果多个模式匹配,.Pattern
只报告其中的模式匹配的是 第一个 其中 在 -Pattern
参数 .
这是一个简单的例子,使用字符串数组模拟来自文件的行作为输入:
'A fool and',
'his barn',
'are soon parted.',
'foo and bar on the same line' |
Select-String -Pattern ('bar', 'foo') |
Select-Object Line, LineNumber, Pattern
以上结果:
Line LineNumber Pattern
---- ---------- -------
A fool and 1 foo
his barn 2 bar
foo and bar on the same line 4 bar
请注意 'bar'
如何被列为最后一行的 Pattern
值,即使 'foo'
在 输入行 中最先出现,因为 'bar'
在 模式数组 .
之前出现在 'foo'
之前
为了反映首先出现在输入行中的实际模式Pattern
属性,需要做更多的工作:
使用 交替 (|
) 将模式数组表示为 单个正则表达式 ,包裹作为一个整体在 捕获组 ((...)
) - 例如,'(bar|foo)'
)
- 注意:下面使用的表达式
'({0})' -f ('bar', 'foo' -join '|')
动态构造此正则表达式,来自数组(这里的数组文字 'bar', 'foo'
,但您可以替换任何数组变量甚至 (Get-Content $inputFile)
);如果您想将输入模式视为 文字 并且它们恰好包含正则表达式元字符(例如 .
),则需要使用 [regex]::Escape()
对它们进行转义首先.
使用计算的 属性 定义自定义 Pattern
属性 报告捕获组的值,这是每个输入遇到的第一个值行:
'A fool and',
'his barn',
'are soon parted.',
'foo and bar on the same line' |
Select-String -AllMatches -Pattern ('({0})' -f ('bar', 'foo' -join '|')) |
Select-Object Line, LineNumber,
@{ n='Pattern'; e={ $_.Matches[0].Groups[1].Value } }
这会产生(缩写为仅显示最后一场比赛):
Line LineNumber Pattern
---- ---------- -------
...
foo and bar on the same line 4 foo
现在,'foo'
被正确报告为匹配模式。
要报告在每一行所有 模式:
开关 -AllMatches
需要告诉 Select-String
在每一行上找到 所有 匹配项,在 [=40= 中表示] MatchInfo
输出对象的集合。
然后必须枚举 .Matches
集合(通过 .ForEach()
集合方法)以从每个匹配项中提取捕获组值。
'A fool and',
'his barn',
'are soon parted.',
'foo and bar on the same line' |
Select-String -AllMatches -Pattern ('({0})' -f ('bar', 'foo' -join '|')) |
Select-Object Line, LineNumber,
@{ n='Pattern'; e={ $_.Matches.ForEach({ $_.Groups[1].Value }) } }
这会产生(缩写为仅显示最后一场比赛):
Line LineNumber Pattern
---- ---------- -------
...
foo and bar on the same line 4 {foo, bar}
请注意 'foo'
和 'bar'
现在如何在 Pattern
中按照在线遇到的顺序进行报告。
来自@mklement0 的可靠信息和示例足以为我指明正确的方向,以研究和了解有关 Powershell 和对象管道以及计算属性的更多信息。
我终于实现了将 table 和字段名称列表交叉引用到 C# 代码的目标 base.The 输入文件只是 table 和字段名称,管道分隔。 (我遇到的一个小故障是没有在拆分中使用管道,这是一个视觉错误,花了一段时间才终于看到,所以检查一下)。输出是 table 名称、字段名、代码文件名、行号和实际行。它并不完美,但比数百个字段的手动工作要好得多!现在有可能在数据映射和转换项目中进一步实现自动化。考虑过使用 C# 实用程序编程,但这可能需要花同样长的时间来弄清楚和实现,而且比工作的 Powershell 更麻烦。
此时对我来说关键是“工作”!我第一次深入了解 Powershell 的深奥世界。我的解决方案的关键点是使用计算的 属性 来获取输出中的 table 和字段名称,实现表达式可以在某些地方使用,例如构建模式和管道在每个命令之后只传递某些特定的对象(也许这太受限制了,但它比我以前的要好)。
希望这对以后的人有所帮助。我找不到任何足够接近的例子来克服困难,所以问了我的第一个 Whosebug 问题。
$inputFile = "C:\input.txt"
$outputFile = "C:\output.csv"
$results = Get-Content $inputfile
foreach ($i in $results) {
Get-ChildItem -Path "C:\ProjectFolder" -Filter *.cs -Recurse -ErrorAction SilentlyContinue -Force |
Select-String -Pattern $i.Split('|')[1] |
Select-Object @{ n='Pattern'; e={ $i.Split('|')[0], $i.Split('|')[1] -join '|'} }, Filename, LineNumber, line |
Export-Csv $outputFile -Append}
感谢@mklement0 帮助我们在
下面的 Powershell 可以很好地查找源代码文件夹中出现的一长串数据库字段名称。
$inputFile = 'C:\DataColumnsNames.txt'
$outputFile = 'C:\DataColumnsUsages.txt'
Get-ChildItem C:\ProjectFolder -Filter *.cs -Recurse -Force -ea SilentlyContinue |
Select-String -Pattern (Get-Content $inputFile) |
Select-Object Path, LineNumber, line |
Export-csv $outputfile
但是,很多行源代码有多个匹配项,尤其是ADO.NET SQL语句一行有很多字段名。如果字段名称参数包含在匹配输出中,则结果将更直接有用,而无需额外处理,例如将所有内容与原始字段名称列表对齐。例如,如果有源行“BatchId = NewId”,它将匹配字段名列表项“BatchId”。有没有一种简单的方法可以在输出中包含“BatchId”和“BatchId = NewId”?
玩过 matches 对象,但它似乎没有信息。也像这里一样尝试了管道变量,但 X 为空。
$inputFile = 'C:\DataColumnsNames.txt'
$outputFile = 'C:\DataColumnsUsages.txt'
Get-ChildItem C:\ProjectFolder -Filter *.cs -Recurse -Force -ea SilentlyContinue |
Select-String -Pattern (Get-Content $inputFile -PipelineVariable x) |
Select-Object $x, Path, LineNumber, line |
Export-csv $outputile
谢谢。
Microsoft.PowerShell.Commands.MatchInfo
instances that Select-String
输出有 a Pattern
属性 反映了(潜在)array 中的特定模式在给定行 .
-Pattern
并匹配 的模式数
警告是如果多个模式匹配,.Pattern
只报告其中的模式匹配的是 第一个 其中 在 -Pattern
参数 .
这是一个简单的例子,使用字符串数组模拟来自文件的行作为输入:
'A fool and',
'his barn',
'are soon parted.',
'foo and bar on the same line' |
Select-String -Pattern ('bar', 'foo') |
Select-Object Line, LineNumber, Pattern
以上结果:
Line LineNumber Pattern
---- ---------- -------
A fool and 1 foo
his barn 2 bar
foo and bar on the same line 4 bar
请注意 'bar'
如何被列为最后一行的 Pattern
值,即使 'foo'
在 输入行 中最先出现,因为 'bar'
在 模式数组 .
'foo'
之前
为了反映首先出现在输入行中的实际模式Pattern
属性,需要做更多的工作:
使用 交替 (
|
) 将模式数组表示为 单个正则表达式 ,包裹作为一个整体在 捕获组 ((...)
) - 例如,'(bar|foo)'
)- 注意:下面使用的表达式
'({0})' -f ('bar', 'foo' -join '|')
动态构造此正则表达式,来自数组(这里的数组文字'bar', 'foo'
,但您可以替换任何数组变量甚至(Get-Content $inputFile)
);如果您想将输入模式视为 文字 并且它们恰好包含正则表达式元字符(例如.
),则需要使用[regex]::Escape()
对它们进行转义首先.
- 注意:下面使用的表达式
使用计算的 属性 定义自定义
Pattern
属性 报告捕获组的值,这是每个输入遇到的第一个值行:
'A fool and',
'his barn',
'are soon parted.',
'foo and bar on the same line' |
Select-String -AllMatches -Pattern ('({0})' -f ('bar', 'foo' -join '|')) |
Select-Object Line, LineNumber,
@{ n='Pattern'; e={ $_.Matches[0].Groups[1].Value } }
这会产生(缩写为仅显示最后一场比赛):
Line LineNumber Pattern
---- ---------- -------
...
foo and bar on the same line 4 foo
现在,'foo'
被正确报告为匹配模式。
要报告在每一行所有 模式:
开关
-AllMatches
需要告诉Select-String
在每一行上找到 所有 匹配项,在 [=40= 中表示]MatchInfo
输出对象的集合。然后必须枚举
.Matches
集合(通过.ForEach()
集合方法)以从每个匹配项中提取捕获组值。
'A fool and',
'his barn',
'are soon parted.',
'foo and bar on the same line' |
Select-String -AllMatches -Pattern ('({0})' -f ('bar', 'foo' -join '|')) |
Select-Object Line, LineNumber,
@{ n='Pattern'; e={ $_.Matches.ForEach({ $_.Groups[1].Value }) } }
这会产生(缩写为仅显示最后一场比赛):
Line LineNumber Pattern
---- ---------- -------
...
foo and bar on the same line 4 {foo, bar}
请注意 'foo'
和 'bar'
现在如何在 Pattern
中按照在线遇到的顺序进行报告。
来自@mklement0 的可靠信息和示例足以为我指明正确的方向,以研究和了解有关 Powershell 和对象管道以及计算属性的更多信息。
我终于实现了将 table 和字段名称列表交叉引用到 C# 代码的目标 base.The 输入文件只是 table 和字段名称,管道分隔。 (我遇到的一个小故障是没有在拆分中使用管道,这是一个视觉错误,花了一段时间才终于看到,所以检查一下)。输出是 table 名称、字段名、代码文件名、行号和实际行。它并不完美,但比数百个字段的手动工作要好得多!现在有可能在数据映射和转换项目中进一步实现自动化。考虑过使用 C# 实用程序编程,但这可能需要花同样长的时间来弄清楚和实现,而且比工作的 Powershell 更麻烦。
此时对我来说关键是“工作”!我第一次深入了解 Powershell 的深奥世界。我的解决方案的关键点是使用计算的 属性 来获取输出中的 table 和字段名称,实现表达式可以在某些地方使用,例如构建模式和管道在每个命令之后只传递某些特定的对象(也许这太受限制了,但它比我以前的要好)。
希望这对以后的人有所帮助。我找不到任何足够接近的例子来克服困难,所以问了我的第一个 Whosebug 问题。
$inputFile = "C:\input.txt"
$outputFile = "C:\output.csv"
$results = Get-Content $inputfile
foreach ($i in $results) {
Get-ChildItem -Path "C:\ProjectFolder" -Filter *.cs -Recurse -ErrorAction SilentlyContinue -Force |
Select-String -Pattern $i.Split('|')[1] |
Select-Object @{ n='Pattern'; e={ $i.Split('|')[0], $i.Split('|')[1] -join '|'} }, Filename, LineNumber, line |
Export-Csv $outputFile -Append}