Powershell,如何捕获 Select-String 的参数并包含匹配的输出 [英] Powershell, how to capture argument(s) of Select-String and include with matched output

查看:356
本文介绍了Powershell,如何捕获 Select-String 的参数并包含匹配的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

感谢@mklement0 帮助我们解决了Powershell 搜索目录中的代码文件与文本匹配输入 txt 文件.

Thanks to @mklement0 for the help with getting this far with answer given in Powershell search directory for code files with text matching input a txt file.

下面的 Powershell 非常适合在源代码文件夹中查找一长串数据库字段名称的出现.

The below Powershell works well for finding the occurrences of a long list of database field names in a source code folder.

$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"都包含在输出中?和BatchId = NewId"?

However, many lines of source code have multiple matches, especially ADO.NET SQL statements with a lot of field names on one line. If the field name argument was included with the matching output the results will be more directly useful with less additional massaging such as lining up everything with the original field name list. For example if there is a source line "BatchId = NewId" it will match field name list item "BatchId". Is there an easy way to include in the output both "BatchId" and "BatchId = NewId"?

玩过matches对象,但似乎没有信息.也试过像这里这样的管道变量,但 X 为空.

Played with the matches object but it doesn't seem to have the information. Also tried Pipeline variable like here but X is null.

$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 实例,Select-String 输出具有 一个 Pattern 属性,它反映了(潜在的) array 传递给 -Pattern 的模式,这些模式在给定的行上匹配.

The Microsoft.PowerShell.Commands.MatchInfo instances that Select-String outputs have a Pattern property that reflects the specific pattern among the (potential) array of patterns passed to -Pattern that matched on a given line.

警告如果多个模式匹配,.Pattern只报告列出的那些匹配的模式first 其中-Pattern 参数中.

The caveat is that if multiple patterns match, .Pattern only reports the pattern among those that matched that is listed first among them in the -Pattern argument.

这是一个简单的例子,使用一个字符串数组来模拟来自文件的行作为输入:

Here's a simple example, using an array of strings to simulate lines from files as input:

'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'之前.

Note how 'bar' is listed as the Pattern value for the last line, even though 'foo' appeared first in the input line, because 'bar' comes before 'foo' in the pattern array.

要在Pattern属性中反映首先出现在输入行的实际模式,还需要做更多的工作:

To reflect the actual pattern that appears first on the input line in a Pattern property, more work is needed:

  • 使用 alternation (|) 将您的模式数组制定为 单个正则表达式,并作为一个整体包装在 捕获组 ((...)) - 例如,'(bar|foo)')

  • Formulate your array of patterns as a single regex using alternation (|), wrapped as a whole in a capture group ((...)) - e.g., '(bar|foo)')

  • 注意:下面使用的表达式,'({0})' -f ('bar', 'foo' -join '|'),动态构造这个正则表达式,来自一个数组(这里的数组字面量 'bar', 'foo',但你可以替换任何数组变量甚至 (Get-Content $inputFile));如果您想将输入模式视为 literals 并且它们碰巧包含正则表达式元字符(例如 .),则需要使用 [regex]::Escape() 首先.
  • Note: The expression used below, '({0})' -f ('bar', 'foo' -join '|'), constructs this regex dynamically, from an array (the array literal 'bar', 'foo' here, but you can substitute any array variable or even (Get-Content $inputFile)); if you want to treat the input patterns as literals and they happen to contain regex metacharacters (such as .), you'll need to escape them with [regex]::Escape() first.

使用计算属性定义自定义Pattern 属性,该属性报告捕获组的值,这是每个输入行上遇到的值中的第一个:

Use a calculated property to define a custom Pattern property that reports the capture group's value, which is the first among the values encountered on each input line:

'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 } }

这产生(缩写为仅显示最后一场比赛):

This yields (abbreviated to show only the last match):

Line                         LineNumber Pattern
----                         ---------- -------
...

foo and bar on the same line          4 foo

现在,'foo' 被正确地报告为匹配模式.

Now, 'foo' is properly reported as the matching pattern.

报告在每一行中发现的所有模式:

To report all patterns found on each line:

  • Switch -AllMatches 需要告诉 Select-String 在每一行查找 all 匹配,用 表示>.Matches MatchInfo 输出对象的集合.

  • Switch -AllMatches is required to tell Select-String to find all matches on each line, represented in the .Matches collection of the MatchInfo output objects.

然后必须枚举 .Matches 集合(通过 .ForEach() 集合方法)以从每个匹配中提取捕获组值.

The .Matches collection must then be enumerated (via the .ForEach() collection method) to extract the capture-group value from each match.

'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 }) } }

这产生(缩写为仅显示最后一场比赛):

This yields (abbreviated to show only the last match):

Line                         LineNumber Pattern
----                         ---------- -------
...

foo and bar on the same line          4 {foo, bar}

注意 'foo''bar' 现在如何在 Pattern 中按顺序报告遇到就行.

Note how both 'foo' and 'bar' are now reported in Pattern, in the order encountered on the line.

这篇关于Powershell,如何捕获 Select-String 的参数并包含匹配的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆