[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[问题求助] PowerShell绑定的文本和键同步排序和修改

本帖最后由 meixi 于 2022-11-30 09:45 编辑

大家好!
下面这个功能我已经有相关的程序来实现了, 现在想使用Powershell代码也实现一下,
个人感觉应该可以通过有序哈希表键值 加 数组排序来实现, 但对于这个例子, 两重排序, 键与值同步修改, 水平有限!
下面的图片, 左侧是处理前的文本, 右侧黑框中是处理后的文本




要处理的内容整体分为三部分:

第①部分是 ---> 第1行: 总是以/开头, 其后的文本是随机的, 该行不参与处理, 永远不变
________________________________________________________________________________
第②部分是 ---> 第2行至第1个以#bub Bub开头的行之间的内容【即蓝框之前的内容】
这部分是所有要处理的键, 它们很有规律, 为了便于理解, 我把它分为 A B C 3个区【图中红框部分】:
A区【空格:之前的文本】可以是( 非# 非: ) 开头的任意文本或字符
------------------------------------------------------------
B区【空格:至空格;;之间, 即红框里的彩色文本】其中bub.Bub是固定的, 后面跟了个序号
这部分非常重要, 这里的序号可以看作是键的ID, 它是唯一的, 在示例中:
bub.Bub11和所有键下面的#bub Bub11开头的行是绑定的, 需要同步更新, 例如:
bub.Bub11若改成了bub.Bub2 则下面的#bub Bub11也需要相应地改成#bub Bub2
------------------------------------------------------------
C区【空格;;之后的文本】由 序号+空格+文本 组成
________________________________________________________________________________
第③部分是 ---> 第1个以#bub Bub开头的行及其以下的所有内容【即蓝框里的内容
这部分与第②部分的键相关联, 在示例中:
ab :bub.Bub11#bub Bub11开头的行相关联, 相绑定,  该行下面的文本相当于键的值

某个键与其对应的#bub Bub开头的行及其下值的对应关系, 在图片中用相同的颜色表现出来了
________________________________________________________________________________________________
★★★★★处理过程★★★★★
先对第②部分所有的键进行排序, 规则如下:

按照A区的字母从a-z排序
若遇到相同字母的, 则按C区的序号大小排序, 在示例中:
A区有两个ab键, 一个键C区的序号是1, 另一个键C区的序号是7, 则1的在上, 7的在下

★★★在上面排序的同时, C区的序号也相应的修改, 在示例中:
●对于两个ab键
排在第1位的ab键的C区的序号如果不是1则改为1
排在第2位的ab键的C区的序号如果不是2则改为2, 以此类推
●对于1个ac键和1个hc键
因为只有1个, 所以直接将C区的序号改为1

★★★在上面排序的同时, 把B区序号ID依次修改为1-1000, 在示例中:
键的序号ID原来是 10 11 18 65 经过上面的排序后, 应分别改成 1 2 3 4

★★★在上面排序的同时, 所有键下面的, 相对应的#bub Bub开头的行及其下的值也同步修改和排序:
注意:
所有【#bub Bub开头的行】其下的值【内部的空行、行前空白符】要原样保留
所有【#bub Bub开头的行】前面只保留一个空行
________________________________________________________________________________
最后修改每个键相对应的【#bub Bub开头的行的m字母】后面的内容
格式:
m ;;A区文本 + 制表符tab + C区的文本
________________________________________________________________________________
有个例外:
如果某个键没有匹配到与其相对应的【#bub Bub开头的行】, 在示例中: hc 键
则新建该行,在其下加文字: 我是新建的
  1. $s = @'
  2. /abc
  3. ab :bub.Bub11 ;;7 我原是Bub11改为Bub2序号2
  4. ab :bub.Bub10 ;;1 我原是Bub10改为Bub1序号1
  5. ac :bub.Bub18 ;;2 我原是Bub18改为Bub3序号1
  6. hc :bub.Bub65 ;;6 我原是Bub65改为Bub4序号1
  7. #bub Bub10 m ;;7
  8. 我之前在Bub10
  9. 最后在Bub1
  10. #bub Bub18 m ;;6
  11. 我之前在Bub18
  12. #前面有一个空格,上面有空行
  13. 最后在Bub3
  14. #bub Bub11 m ;;9
  15. 我之前在Bub11
  16. #bub Bub前面没空格
  17. 最后在Bub2
  18. '@
  19. #Todo: 处理代码
  20. <# 处理后的文本
  21. /abc
  22. ab :bub.Bub1 ;;1 我原是Bub10改为Bub1序号1
  23. ab :bub.Bub2 ;;2 我原是Bub11改为Bub2序号2
  24. ac :bub.Bub3 ;;1 我原是Bub18改为Bub3序号1
  25. #bub Bub1 m ;;ab 1 我原是Bub10改为Bub1序号1
  26. 我之前在Bub10
  27. 最后在Bub1
  28. #bub Bub2 m ;;ab 2 我原是Bub11改为Bub2序号2
  29. 我之前在Bub11
  30. #bub Bub前面没空格
  31. 最后在Bub2
  32. #bub Bub3 m ;;ac 1 我原是Bub18改为Bub3序号1
  33. 我之前在Bub18
  34. #前面有一个空格,上面有空行
  35. 最后在Bub3
  36. #bub Bub4 m ;;hc 1 我原是Bub65改为Bub4序号1
  37. 我是新建的
  38. #>
复制代码

描述问题时建议不要带入解决问题的思路,否则很容易影响问题的理解的,还有请使用具体示例,比如你问题里的那个文本里内容完全是就是干扰,还以为是以文本的内容来进行处理。
总之看了好久,才总算理解了,给你个思路吧:
①:读取文件内容放入变量
②:从文件内容变量中匹配提取需要排序的内容存放在数组中(即第二部分,“ XX :bub.BubYY ;;ZZ -----------”这种形式的)
③:从文件内容变量中匹配提取键与值并构建哈希表(非必需)
④:按数组内容中的字母(XX)部分,排序数组(第一遍)
⑤:按数组内容中的序号(ZZ)部分,排序数组(第二遍)
⑥:遍历数组,按数组序号修改数组内容的键(bub.BubYY)部分和序号(ZZ)部分,并写入文件(第一遍)
⑦:遍历数组,从数组内容中找到键部分(bub.BubYY),索引哈希表(或从文件内容匹配内容),修改内容后写入文件(第二遍)

TOP

回复 2# Five66

感谢建议,

感觉我描述的可能太详细了, 并没有带入解决问题的思路, 只是在开头提了一下, 使用哈希和数组
最后面的代码, 有需要处理的字符串变量和处理之后的结果, 方便输出后对照

TOP

  1. $a=New-Object Collections.Specialized.OrderedDictionary
  2. $h='/abc'
  3. if($s -match "(?s)(?<=$h\s+).+?(?=\s+#)"){$c=$matches[0]}
  4. $c -split '\n'|%{
  5.     if($_ -match '^(\S+)\s+:((\D+)(\d+))\s*;;\S*\s*([^\r\n]+)'){
  6.         $d=$matches
  7.         if($s -match "(?s)(?<=\r\n#$($d[2]) m ;;.*?\r\n).+?(?=\s*#bub Bub\d+ m ;;|\s*$)"){
  8.             $a[$d[1]]+=,@($d[3],$d[5],$matches[0],$d[4])
  9.         }else{$a[$d[1]]+=,@($d[3],$d[5],'我是新建的',$d[4])}
  10.     }
  11. }
  12. $a.Keys|%{
  13.     $e=$_
  14.     $a.$e|sort{[int]$_[3]}|%{
  15.         $j++
  16.         $f+=@("{0} :{1}{2} ;;{3} {4}" -f $e,$_[0],++$i,$j,$_[1])
  17.         $g+=@("#bub Bub$i m ;;$e`t$($_[1])`r`n$($_[2])")
  18.     }
  19.     $j=0
  20. }
  21. "$h`r`n$($f -join "`r`n")`r`n`r`n$($g -join "`r`n`r`n")"
复制代码

TOP

回复 4# idwma

多谢, 好像A区没有排序, 例如, 我把ac和hc交换一下, 输出后hc仍然在上
  1. $s = @'
  2. /abc
  3. ab :bub.Bub11 ;;7 我原是Bub11改为Bub2序号2
  4. ab :bub.Bub10 ;;1 我原是Bub10改为Bub1序号1
  5. hc :bub.Bub65 ;;6 我原是Bub65改为Bub4序号1
  6. ac :bub.Bub18 ;;2 我原是Bub18改为Bub3序号1
  7. #bub Bub10 m ;;7
  8. 我之前在Bub10
  9. 最后在Bub1
  10. #bub Bub18 m ;;6
  11. 我之前在Bub18
  12. #前面有一个空格,上面有空行
  13. 最后在Bub3
  14. #bub Bub11 m ;;9
  15. 我之前在Bub11
  16. #bub Bub前面没空格
  17. 最后在Bub2
  18. '@
复制代码

TOP

  1. $a=@{}
  2. $h='/abc'
  3. if($s -match "(?s)(?<=$h\s+).+?(?=\s+#)"){$c=$matches[0]}
  4. $c -split '\n'|%{
  5.     if($_ -match '^(\S+)\s+:((\D+)(\d+))\s*;;\S*\s*([^\r\n]+)'){
  6.         $d=$matches
  7.         if($s -match "(?s)(?<=\r\n#$($d[2]) m ;;.*?\r\n).+?(?=\s*#bub Bub\d+ m ;;|\s*$)"){
  8.             $a[$d[1]]+=,@($d[3],$d[5],$matches[0],$d[4])
  9.         }else{$a[$d[1]]+=,@($d[3],$d[5],'我是新建的',$d[4])}
  10.     }
  11. }
  12. $a.Keys|sort|%{
  13.     $e=$_
  14.     $a.$e|sort{[int]$_[3]}|%{
  15.         $j++
  16.         $f+=@("{0} :{1}{2} ;;{3} {4}" -f $e,$_[0],++$i,$j,$_[1])
  17.         $g+=@("#bub Bub$i m ;;$e`t$j $($_[1])`r`n$($_[2])")
  18.     }
  19.     $j=0
  20. }
  21. "$h`r`n$($f -join "`r`n")`r`n`r`n$($g -join "`r`n`r`n")"
复制代码
回复 5# meixi

TOP

多谢, 想请教几个问题

1.第一行这个可以免修改吗? 因为第一行是不需要动的, 不然每次都要手改一下
$h='/abc'

2. $a=@{} 我换成原来的$a=New-Object Collections.Specialized.OrderedDictionary也可以, 感觉用C#的这个, 应该快点

3.代码中类似 $x += @(xxx) 这种数组操作在字符多的时候, 处理的时间太长, 能换成C#的数组列表来处理吗

TOP

回复 7# meixi


    2,3行改一下
  1. if($s -match "(?s)(?<=^(?<h>/.*)\s+).+?(?=\s+#)"){$c=$matches[0];$h=$matches.h}
复制代码
C#数组是什么不会呀

TOP

本帖最后由 5i365 于 2022-12-1 14:32 编辑

回复 8# idwma

C#数组就是这个 $t = New-Object System.Collections.ArrayList

https://blog.csdn.net/weixin_30734435/article/details/97778376
本人所发所有贴子或代码, 诸大侠若认为有改进之处,请不吝赐教,感激不尽!

TOP

回复 9# 5i365

对, 就是这个

TOP

  1. $a=@{}
  2. if($s -match "(?s)(?<=^(?<h>/.*)\s+).+?(?=\s+#)"){$c=$matches[0];$h=$matches.h}
  3. $c -split '\n'|%{
  4.     if($_ -match '^(\S+)\s+:((\D+)(\d+))\s*;;\S*\s*([^\r\n]+)'){
  5.         $d=$matches
  6.         if($s -match "(?s)(?<=\r\n#$($d[2]) m ;;.*?\r\n).+?(?=\s*#bub Bub\d+ m ;;|\s*$)"){
  7.             $a[$d[1]]+=,@($d[3],$d[5],$matches[0],$d[4])
  8.         }else{$a[$d[1]]+=,@($d[3],$d[5],'我是新建的',$d[4])}
  9.     }
  10. }
  11. $f = New-Object System.Collections.ArrayList
  12. $g = New-Object System.Collections.ArrayList
  13. $null=$a.Keys|sort|%{
  14.     $e=$_
  15.     $a.$e|sort{[int]$_[3]}|%{
  16.         $j++
  17.         $f.add(("{0} :{1}{2} ;;{3} {4}" -f $e,$_[0],++$i,$j,$_[1]))
  18.         $g.add("#bub Bub$i m ;;$e`t$j $($_[1])`r`n$($_[2])")
  19.     }
  20.     $j=0
  21. }
  22. "$h`r`n$($f -join "`r`n")`r`n`r`n$($g -join "`r`n`r`n")"
复制代码
1

评分人数

    • meixi: 乐于助人技术 + 1

TOP

回复 11# idwma

不比不知道, 这一改真是快了

TOP

返回列表