目前,当我在 powershell 中查看一堆文件中的字符串时,我使用以下命令:
PS: C:\> ls -r | Select-String "dummy" | ls -r
这样就列出了所有包含该字符串的文件。如果我执行以下任一操作
PS: C:\> ls -r | Select-String "dummy" | ls -r | cat
PS: C:\> ls -r | Select-String "dummy" | cat
它将再次搜索并 cat 所有包含该字符串的文件,但所有内容都会出现在一个块中,例如
file 1 line 1
file 1 line 2
file 2 line 1
file 3 line 1
file 4 line 1
但是没有办法知道哪一行在哪个文件中。有没有办法让它列出类似以下内容的内容:
File 1.txt:
file1 line1
file2 line2
File 2.txt:
file2 line1
等等。最好只写一行,但不是必须的
答案1
有人可能会说这不是一行代码,但它在任何情况下都应该有效(“应该”的意思是我没有测试过,但脚本应该是正确的):
Get-ChildItem -Recurse | Where-Object {(Select-String -InputObject $_ -Pattern 'dummy' -Quiet) -eq $true} | ForEach-Object {Write-Output $_; Get-Content $_}
扩展并附有评论:
# Get a listing of all files within this folder and its subfolders.
Get-ChildItem -Recurse |
# Filter files according to a script.
Where-Object {
# Pick only the files that contain the string 'dummy'.
# Note: The -Quiet parameter tells Select-String to only return a Boolean. This is preferred if you just need to use Select-String as part of a filter, and don't need the output.
(Select-String -InputObject $_ -Pattern 'dummy' -Quiet) -eq $true
} |
# Run commands against each object found.
ForEach-Object {
# Output the file properties.
Write-Output $_;
# Output the file's contents.
Get-Content $_
}
如果你真的想看得更短,这里有一个“高尔夫”版本。这绝对更接近“单行”的水平。
ls -R|?{$_|Select-String 'dummy'}|%{$_;gc $_}
除了明显使用别名、空格折叠和参数名称截断之外,您可能还需要注意“完整”版本和“高尔夫”版本之间的以下显著差异:
Select-String
被换成使用管道输入而不是-InputObject
。-Pattern
省略了参数名称,Select-String
因为该参数名称的使用是可选的。- 该
-Quiet
选项已从 中删除Select-String
。过滤器仍将工作,但需要更长时间,因为Select-String
它将处理每个完整文件,而不是在第一个匹配的行后停止。 -eq $true
已从过滤规则中省略。当过滤脚本已经返回布尔值时,如果您只是希望它在布尔值为真时起作用,则无需添加比较运算符和对象。- (还请注意,这将适用于某些非布尔值,就像在此脚本中一样。这里,匹配将导致填充的数组对象,该对象被视为真,而非匹配将返回一个空数组,该数组被视为假。)
Write-Output
被省略。如果未使用命令给出对象,PowerShell 将尝试将此作为默认操作执行。
如果您不需要所有文件的属性,而只想要文件内容前一行的完整路径,则可以使用此方法:
ls -R|?{$_|Select-String 'dummy'}|%{$_.FullName;gc $_}