我正在构建一个脚本,该脚本将访问大量文件并提取一个特定的字符串,以便分配为变量。
字符串在所有文件中都是相似的,这不是问题所在。我能够使这个过程作为一个单独的事件发挥作用(定义一个单一的源文件(
$hostname_import = select-string .test.txt -Pattern 'hostname ABC-.+'
$hostname = $hostname_import -replace '.+ ',''
以上内容将输出目标文件中标识的特定主机名(第二个功能是修剪单词hostname和空格(,然后我可以根据需要使用该变量继续执行各种操作。
我遇到的问题是在foreach循环中执行这个函数,这样我就可以获取初始文件——执行select字符串函数(或类似函数(,然后在循环中按预期执行数据修改。
对于上下文——我正在浏览配置文件——并基于这些配置构建一个单独的文件来报告结果——报告构建的一部分需要设备的主机名。
--第1版:与我的橡皮鸭协商后,我将尝试将这些文件作为CSV导入,以便潜在地达成解决方案。
- 感谢@Otter帮我度过难关。我以前有一个脚本使用了这个函数,但无论出于什么原因,我都无法按预期执行该函数。我以前的脚本和这次的不同之处在于$_.Fullname
巨大的帮助!
Select-String
可以通过其-Path
或-LiteralPath
参数,作为路径的数组和/或通配符表达式,直接处理多个文件。
它不支持的是传递目录路径,以便处理其中的文件(更不用说递归地了(,因此您必须将Get-ChildItem
(可能与-Recurse
一起(的结果通过管道传输到Select-String
调用。
以下示例使用后一种技术,在当前目录子树中的所有*.config
文件上循环:
Get-ChildItem -File -Recurse -Filter *.config |
Select-String -Pattern 'hostname ABC-(.+)' |
ForEach-Object {
$sourceFilePath = $_.Path
$hostName = $_.Matches[0].Groups[1].Value
}
请注意,在正则表达式模式中使用了捕获组((...)
(,它允许通过Select-String
输出的Microsoft.PowerShell.Commands.MatchInfo
实例仅从整体匹配中提取感兴趣的子字符串。这消除了对CCD_ 11操作的需要;有关详细信息,请参阅底部部分。
请注意,每个文件可能会报告多个匹配;如果您知道只有一个(或只对第一个 如何仅提取匹配行/行部分的文本(字符串(: 当您在字符串上下文(如-replace
(中直接Select-String
输出对象(类型为Microsoft.PowerShell.Commands.MatchInfo
(时,如果给定了文件参数,则生成的字符串表示包含的比行文本更多,因为输入文件路径以行文本开头,后面跟着:
;例如:C:pathtofile.config:hostname ABC-foo
要仅提取行文本,请使用.Line
属性直接作为字符串。
- 注意:在PowerShell(Core(7+中,您现在可以通过传递
-Raw
开关,要求Select-String
直接输出字符串(匹配行(
要仅提取正则表达式匹配的行的部分,请使用.Matches
属性(如果还传递了用于文字子字符串匹配的-SimpleMatch
开关,则为n/a(,如上所示。
.Matches
是System.Text.RegularExpressions.Match
实例的集合(如果传递了-AllMatches
开关,则只能有多个元素(,每个实例的.Value
属性都包含与模式整体匹配的文本。如果
-Pattern
正则表达式包含捕获组((...)
(,则每个Match
实例的.Groups
集合(本身由Match
实例组成(包含这些组捕获的内容,从索引1
开始;CCD_ 34属性再次包含捕获的文本。
听起来您需要一个Get-ChildItem
,它将获取文件夹中的所有文件,然后将输出管道传输到Foreach-Object
循环,该循环将引用每个文件。
请注意,我添加了-recurse
开关,以防您也需要提取子文件夹文件。
尝试以下操作:
Get-Childitem -path "C:PathToFolder" -recurse | Foreach-Object {
$hostname_import = select-string $_.Fullname -Pattern 'hostname ABC-.+'
$hostname = $hostname_import -replace '.+ ',''
# The rest of your logic goes here
}