Board logo

标题: [问题求助] PowerShell将多行文本中符合条件的字段提取为hash表的键值对 [打印本页]

作者: 5i365    时间: 2022-3-30 23:24     标题: PowerShell将多行文本中符合条件的字段提取为hash表的键值对

我想把多行文本中, #开始  #结束 中间那几行中满足条件 "xxx", //xx 的字段,即粉色字部分, 提取为hash表的键值对,即蓝色字部分
最后期待的结果像下面这样, 即:将hash表所有键的值先分别用""括起来后, 然后再连成一行,值与值之间有空格, 还有,在第一个键值后面加一对空双引号,即下面红色引号
"在东京" "" "在纽约" "在刚果"

提取键值对的代码还没有写, 感觉要用正则匹配, 正则的规则,双引号""内是值, //后是键【,前后可能会有空格】, 估计会用到 $1$2的交换

将所有键的值连成一行的代码写了, 但是在第一个键值后面添加一对空引号的代码还没有写,

求路过高手指教, 提前感谢


@"
岁月难得沉默
秋风厌倦漂泊
夕阳赖着不走
挂在墙头舍不得我
昔日伊人耳边话
已和潮声向东流
再回首
#开始
      黄种人"在东京", //日本
             白人"在纽约", //美国

"在刚果",//南非

        
黑人//印度

#结束
往事也随枫叶一片片落
爱已走到尽头
恨也放弃承诺
命运自认幽默
想法太多由不得我
壮志凌云几分酬
知己难逢几人留
"@

#Todo 提取键值对的代码还未写

$Args = [ordered]@{
日本 = "在东京"

美国  = "在纽约"

南非  = "在刚果"

}

$Args.Values | %{ '"' + $_ + '"' } | tee -var a | Out-Null
$a -join ' '

#期待输出的结果
"在东京" "" "在纽约" "在刚果"
作者: for_flr    时间: 2022-3-31 09:45

  1. $pattern1="#开始(.*)#结束"
  2. $pattern2='"(\w+)",\s?//(\w+)'
  3. $hash=@{}
  4. $txt=(gc a.txt) -join "|"
  5. if($txt -match $pattern1){
  6.     $target=$matches[1].split('|')
  7. }
  8. foreach($line in $target){
  9.     if($line -match $pattern2){
  10.         $hash[$matches[2]]=$matches[1]
  11.     }
  12. }
  13. $hash
  14. $hash.values
  15. $null=[console]::readkey()
复制代码

作者: 5i365    时间: 2022-3-31 10:15

回复 2# for_flr


   感谢大侠分享, 有点难度, 我得慢慢消化
作者: for_flr    时间: 2022-3-31 10:17

if($line -match $pattern2){$hash[$matches[2]]=$matches[1]}
就一条命令创建键值对,不算太绕吧。

其他的只是为了取#开始#结束之间的文本。
一起坐等高手。
作者: 5i365    时间: 2022-3-31 10:29

回复 4# for_flr

嗯, 大侠的代码确实好理解, 前面发贴时, 先感觉花了两段匹配, 就感觉绕了, 其实这样分段取值好理解,
作者: 5i365    时间: 2022-3-31 10:37

回复 4# for_flr


   加了有序hash类型, 防止参数位置变化, 现在就剩下另一个小问题了,
  1. $s = @"
  2. 岁月难得沉默
  3. 秋风厌倦漂泊
  4. 夕阳赖着不走
  5. 挂在墙头舍不得我
  6. 昔日伊人耳边话
  7. 已和潮声向东流
  8. 再回首
  9. #开始
  10.       黄种人"在东京", //日本
  11.              白人"在纽约", //美国
  12. "在刚果",//南非
  13.         黑人//印度
  14. #结束
  15. 往事也随枫叶一片片落
  16. 爱已走到尽头
  17. 恨也放弃承诺
  18. 命运自认幽默
  19. 想法太多由不得我
  20. 壮志凌云几分酬
  21. 知己难逢几人留
  22. "@
  23. $txt = $s -split '\n' -join "|"
  24. $pattern1 = "#开始(.*)#结束"
  25. $pattern2 = '"(\w+)",\s?//(\w+)'
  26. $hash = [ordered]@{ }
  27. if ($txt -match $pattern1)
  28. {
  29. $target = $matches[1].split('|')
  30. }
  31. $target
  32. foreach ($line in $target)
  33. {
  34. if ($line -match $pattern2)
  35. {
  36. $hash[$matches[2]] = $matches[1]
  37. }
  38. }
  39. #$hash
  40. $hash.values
  41. #$null = [console]::readkey()
复制代码

作者: 5i365    时间: 2022-3-31 10:40

回复 4# for_flr


   大侠请教一个小问题, 上面我改的代码中, 下面这句, 为什么有时 \n不行, 要\r\n ? 而有时反过来才行 真是怪了

$txt = $s -split '\n' -join "|"
作者: for_flr    时间: 2022-3-31 10:59

  1. $pattern2 = '"(\w+)",\s?//(\w+)' 改成 $pattern2 = '("\w+"),\s?//(\w+)'
复制代码
这样可以把双引号添进键值。
  1. $abc=$hash.values.split()
  2. $abc[0]+'""'+$abc[1..$abc.count]
复制代码
将键值连成一行。
作者: 5i365    时间: 2022-3-31 11:06

回复 8# for_flr


感谢分享帮助, 学习了
作者: 5i365    时间: 2022-3-31 11:38

本帖最后由 5i365 于 2022-3-31 11:41 编辑

回复 8# for_flr


   大侠好, 想请教一个问题, 下面的代码, 输出的结果是: hash表对象的属性,即蓝色字, 我想输出hash对象的定义的字符串,即红色字,

我找了下相关函数没有找到, 我印象中在哪里看到过, 字符串转对象, 对象转字符串,还有一些对象, 是可以互转的

Name                           Value
----                           -----
日本                             "在东京"
美国                             "在纽约"
南非                             "在刚果"

------------------------------------------------------------------
$hash = [ordered]@{

日本 = "在东京"


美国 = "在纽约"


南非 = "在刚果"

}


  1. $s = @"
  2. 岁月难得沉默
  3. 秋风厌倦漂泊
  4. 夕阳赖着不走
  5. 挂在墙头舍不得我
  6. 昔日伊人耳边话
  7. 已和潮声向东流
  8. 再回首
  9. #开始
  10.       黄种人"在东京", //日本
  11.              白人"在纽约", //美国
  12. "在刚果",//南非
  13.         黑人//印度
  14. #结束
  15. 往事也随枫叶一片片落
  16. 爱已走到尽头
  17. 恨也放弃承诺
  18. 命运自认幽默
  19. 想法太多由不得我
  20. 壮志凌云几分酬
  21. 知己难逢几人留
  22. "@
  23. $txt = $s -split '\n' -join "|"
  24. $pattern1 = "#开始(.*)#结束"
  25. $pattern2 = '("\w+"),\s?//(\w+)'
  26. $hash = [ordered]@{ }
  27. if ($txt -match $pattern1)
  28. {
  29.         $target = $matches[1].split('|')
  30. }
  31. foreach ($line in $target)
  32. {
  33.         if ($line -match $pattern2)
  34.         {
  35.                 $hash[$matches[2]] = $matches[1]
  36.         }
  37. }
  38. $hash
复制代码

作者: 5i365    时间: 2022-3-31 12:35

本帖最后由 5i365 于 2022-3-31 13:35 编辑

回复 8# for_flr


   我想了一个新的插入方法
$hash.Insert(1, "", "")
($hash.values | %{ '"' + $_ + '"' }) -join " "
作者: 5i365    时间: 2022-3-31 17:25

回复 8# for_flr


   把hash表对象定义,还原回字符串, 我找到了关键的代码, 但是还差首和尾的定义, 怎么接上?
  1. $hash.GetEnumerator() | %{
  2. $_.key + "=" + $_.Value
  3. }
复制代码





欢迎光临 批处理之家 (http://bathome.net./) Powered by Discuz! 7.2