从文件夹中的所有文本文件中提取与模式匹配的行到单个输出文件

Extract lines matching a pattern from all text files in a folder to a single output file

我正在尝试提取文件夹中所有文件中以“%%”开头的每一行,然后将这些行复制到单独的文本文件中。目前在 PowerShell 代码中使用此代码,但我没有得到任何结果。

$files = Get-ChildItem "folder" -Filter *.txt
foreach ($file in $files)
{
if ($_ -like "*%%*")
{
Set-Content "Output.txt" 
}  
}
ls *.txt | %{
$f = $_
  gc $f.fullname | {
     if($_.StartWith("%%") -eq 1){
        $_ >> Output.txt
     }#end if
  }#end gc
}#end ls

别名

ls - Get-ChildItem
gc - Get-Content
% - ForEach
$_ - Iterator variable for loop
>> - Redirection construct
# - Comment

http://ss64.com/ps/

首先你必须使用

Get-Content

为了得到文件的内容。然后您进行字符串匹配,并在此基础上再次 将内容 设置回文件。使用 get-content 并在 foreach 中放置另一个循环来迭代文件中的所有行。

希望这个逻辑能帮到你

Select-String cmdlet 提供了一个更简单的解决方案(PSv3+ 语法):

(Select-String -Path folder\*.txt -Pattern '^%%').Line | Set-Content Output.txt
  • Select-String 通过其 -Path 参数接受 filename/path 模式,因此,在这种简单的情况下,不需要 Get-ChildItem

    • 相比之下,如果您的输入文件选择是递归的或使用更复杂的条件,则可以将 Get-ChildItem 的输出通过管道传输到 Select-String,如 中所示。
    • 请注意,according to the docsSelect-String 默认情况下假定输入文件是 UTF-8 编码的,但您可以使用 -Encoding 参数更改它;还要考虑下面讨论的 output 编码。
  • Select-String-Pattern 参数需要 正则表达式 而不是通配符表达式。
    ^%% 仅匹配行的 start (^) 处的文字 %%

  • Select-String 输出 [Microsoft.PowerShell.Commands.MatchInfo] objects 包含每个匹配的信息;每个对象的 .Line 属性 包含匹配的输入行的全文。

  • Set-Content Output.txt 将所有匹配行发送到单个输出文件 Output.txt

    • Set-Content 使用系统遗留的 Windows 代码页(8 位单字节编码 - 尽管 documentation 错误地声称 ASCII 文件被生成)。
      如果要显式控制输出编码,使用-Encoding参数;例如,... | Set-Content Output.txt -Encoding Utf8.
    • 相比之下,>,输出重定向运算符 总是 创建 UTF-16LE 文件(PowerShell 调用 Unicode 的编码),Out-File 默认(可以用-Encoding更改)。
      另请注意,> / Out-File 将 PowerShell 的默认格式应用于输入对象以获得写入输出文件的字符串表示形式,而 Set-Content 将输入视为 strings (如有必要,对输入对象调用 .ToString())。在手头的例子中,由于所有输入对象都已经是字符串,所以没有区别(除了字符编码,可能)。

至于你试过的:

  • $_ 在你的 foreach ($file in $files) 中指的是一个 file (一个 [System.IO.FileInfo] 对象),所以你是根据输入文件的 name 而不是其 contents.

  • 有效评估通配符表达式 *%%*
  • 除此之外,通配符模式 *%%* 将匹配输入字符串中的 %% 任何地方 ,而不仅仅是在其 start(您必须改用 %%*)。

  • 缺少 Set-Content "Output.txt" 调用 input,因为它不是管道的一部分,并且在没有管道输入的情况下,没有 -Value 参数已通过。

    • 但是,即使您确实提供了输入,输出文件 Output.txt 也会在 每次迭代 作为一个整体重写 你的 foreach 循环。

我认为 mklement0 使用 Select-String 的建议是可行的方法。添加到他的答案中,您可以将 Get-ChildItem 的输出通过管道传输到 Select-String 中,这样整个过程就变成了一个 Powershell one liner。

像这样:

Get-ChildItem "folder" -Filter *.txt | Select-String -Pattern '^%%' | Select -ExpandProperty line | Set-Content "Output.txt"