Windows 使用powershell从键值对提取值
我有一个包含键值数据的文件。我必须获取该文件中特定密钥的值。我有与Linux等效的命令: 文件: 命令:Windows 使用powershell从键值对提取值,windows,powershell,Windows,Powershell,我有一个包含键值数据的文件。我必须获取该文件中特定密钥的值。我有与Linux等效的命令: 文件: 命令: cat path/file | grep 'key1' | awk -F '=' '{print $2}' 输出: val1 我也想在windows上实现同样的输出。我没有任何在power shell工作的经验,但我尝试了以下方法: Get-Content "path/file" | Select-String -Pattern 'key1' -AllMatches
cat path/file | grep 'key1' | awk -F '=' '{print $2}'
输出:
val1
我也想在windows上实现同样的输出。我没有任何在power shell工作的经验,但我尝试了以下方法:
Get-Content "path/file" | Select-String -Pattern 'key1' -AllMatches
但我得到的输出是这样的:
key1=val1
我做错了什么?
<# required powershell version 5.1 or later
@'
key1=val1
key2=val2
'@ | out-file d:\temp.txt
#>
(Get-Content d:\temp.txt | ConvertFrom-StringData).key1
(获取内容d:\temp.txt | convertfromStringData)。键1
注意:
- 使用特定的输入格式(
line),提供最简单的解决方案,使用;请注意,它忽略key=value
周围的空格以及值后面的尾随空格=
- 下面的答案主要集中在如何在PowerShell中实现类似于
和grep
的功能awk
它不是您的方法的直接等价物,而是一种更快的PowerShell惯用解决方案,使用以下语句:
# Create a sample file
@'
key1=val1
key2=val2
'@ > sample.txt
# -> 'val1'
switch -Regex -File ./sample.txt { '^\s*key1=(.*)' { $Matches[1]; break } }
选项隐式地对输入文件的每一行执行一个操作(多亏了-Regex
),结果可在中找到-file
因此返回正则表达式中第一个(也是唯一一个)捕获组($Matches[1]
)匹配的内容<代码>中断立即停止处理(…)
一个更简洁但速度较慢的选项是组合
-match
和运算符,但请注意,只有当只有一行匹配时,此选项才会按预期工作:
((Get-Content ./sample.txt) -match '^\s*key1=' -split '=')[1]
还要注意的是,这总是涉及到读取整个文件,通过将所有行预先加载到一个数组中
一个相对较慢的版本-由于使用cmdlet,因此隐式使用管道-修复了您的尝试:
(Select-String -List '^\s*key1=(.*)' ./sample.txt).Matches[0].Groups[1].Value
注:
- 输出类型为的包装器对象,该对象围绕匹配字符串包装元数据,而不是直接返回它们(就像
那样)grep
是包含匹配详细信息的属性,它允许访问正则表达式中捕获组(.Matches
)捕获的内容,但如何访问该信息并不十分明显(…)
开关确保处理在第一次匹配时停止,但请注意,这仅适用于直接文件参数,而不是通过-List
单独管道文件行获取内容
- 请注意,
用于在一行(输入对象)中查找多个匹配项,因此此处不需要-AllMatches
另一个缓慢的解决方案,与脚本块一起使用,其中每一行都进入键和值部分,如下所示: 警告:即使在找到感兴趣的键之后,也会始终处理所有行
- 为了防止出现这种情况,您可以将
附加到命令中| Select Object-First 1
- 不幸的是,从PowerShell 7.1开始,无法根据需要直接从脚本块退出管道;见长期存在的问题
- 请注意,
不能按预期工作-除非将管道包装在一个伪循环语句中(例如,break
)来中断do{…}while($false)
- 请注意,
awk
步骤,该步骤将=
上的字符串拆分并选择第二部分。PowerShell等价物是('key=value'-split'=')[1]
,您需要在|Foreach对象{…}
中使用它。(这几乎是但不完全是答案。)这足以解决这个问题
(Select-String -List '^\s*key1=(.*)' ./sample.txt).Matches[0].Groups[1].Value
Get-Content ./sample.txt | ForEach-Object {
$key, $val = $_ -split '='
if ($key -eq 'key1') { $val }
}