Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 使用powershell从键值对提取值_Windows_Powershell - Fatal编程技术网

Windows 使用powershell从键值对提取值

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

我有一个包含键值数据的文件。我必须获取该文件中特定密钥的值。我有与Linux等效的命令:

文件:

命令:

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
注意:

  • 使用特定的输入格式(
    key=value
    line),提供最简单的解决方案,使用;请注意,它忽略
    =
    周围的空格以及值后面的尾随空格

  • 下面的答案主要集中在如何在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 } 
}