Board logo

标题: [问题求助] PowerShell同步修改特定行的序号并排序 [打印本页]

作者: meixi    时间: 2022-12-2 09:43     标题: PowerShell同步修改特定行的序号并排序


这个贴子和右边链接里的情况有很多相似之处 http://www.bathome.net/thread-64532-1-1.html
下面图片左侧是要修改的文本, 右侧是处理后的文本, 文本颜色仅表示对应关系
如果下方图片显示不清, 请打开链接  i.ibb.co/Fb5Y7H2/8.png


要处理的文本分为两部分:
第1个以#bub Bub开头的行之前是第1部分【蓝框之前的内容】
之后是第2部分【蓝框中的内容】
----------------------------------------------------------------------------------------------------------------------
处理过程:

①第1部分的文本中, 如果某行中存在 :bub.BubXX 则按先后顺序修改XX的序号【XX是1至4位的数字】, 在示例中:
包含 :bub.Bub11 的行是先出现的, 则把11改为1
包含 :bub.Bub65 的行是第2出现的, 则把65改为2
其它的以此类推

②第1部分中包含 :bub.BubXX 的行 与 第2部分中 #bub.BubXX 开头的行是互相绑定的, XX需要同步修改, 在示例中:
第1部分中 :bub.Bub11 改为 :bub.Bub1 之后,  第2部分的 #bub.Bub11 要同步改为 #bub.Bub1
相互绑定的行在图中已用同种颜色标记起来了

③上面XX同步修改的同时, 把#bub.BubXX开头的行尾部的m字母后面修改成如下格式:
m + 空格 + ;; + 与其绑定的 :bub.BubXX 冒号之前的文本
在示例中:
ab :bub.Bub11 和 #bub Bub11 m 是绑定的, 同步修改后应该是
ab :bub.Bub11 改为 ab :bub.Bub1
#bub Bub11 m 改为 #bub Bub1 m ;;ab

④如果第1部分的:bub.BubXX没匹配到的#bub BubXX的行,则新建#开头的行, 在示例中:
ZZ :bub.Bub26 匹配不到#bub Bub26的行,则把26改为5之后,新建下列的行
#bub Bub5 m ;;ZZ
我是新加的

⑤最后将第2部分的内容, 按XX的先后顺序排序

注意:
上面的操作基本是在改序号和修改m字母后面的内容, 其它内容不能改动
#bub.BubXX开头的行前只保留一个空行
  1. $s= @'
  2. ab $( ) :bub.Bub11
  3. - :TA_Fbv "T " * $q$\m.co
  4. 中国 ac :bub.Bub65 * a.b
  5. >windows - china * cdef
  6. 小 日本 japen :bub.Bub10 ;;c.e
  7. |
  8. ac ${ } :bub.Bub18
  9. <
  10. ZZ :bub.Bub26
  11. #bub Bub10 m ;;1 小日本
  12. 我之前序号是10
  13.   最后是3
  14. #bub Bub
  15. #bub Bub11 m
  16. 我之前序号是11
  17.   最后是1
  18. #bub Bub 11
  19. #bub Bub18 m ;;6
  20. 我之前序号是18
  21.   最后是4
  22. #bub Bub 4
  23. #bub Bub65 m ;;
  24. 我之前序号是18
  25.   最后是2
  26. '@
  27. #Todo 处理代码
  28. <# 处理后的效果
  29. ab $( ) :bub.Bub1
  30. - :TA_Fbv "T " * $q$\m.co
  31. 中国 ac :bub.Bub2 * a.b
  32. >windows - china * cdef
  33. 小 日本 japen :bub.Bub3 ;;c.e
  34. |
  35. ac ${ } :bub.Bub4
  36. <
  37. ZZ :bub.Bub5
  38. #bub Bub1 m ;;ab $( )
  39. 我之前序号是11
  40.   最后是1
  41. #bub Bub 11
  42. #bub Bub2 m ;;中国 ac
  43. 我之前序号是18
  44.   最后是2
  45. #bub Bub3 m ;;小 日本 japen
  46. 我之前序号是10
  47.   最后是3
  48. #bub Bub
  49. #bub Bub4 m ;;ac ${ }
  50. 我之前序号是18
  51.   最后是4
  52. #bub Bub 4
  53. #bub Bub5 m ;;ZZ
  54. 我是新加的
  55. #>
复制代码

作者: WHY    时间: 2022-12-2 20:35

本帖最后由 WHY 于 2022-12-3 10:12 编辑
  1. $s = @'
  2. ab $( ) :bub.Bub11
  3. - :TA_Fbv "T " * $q$\m.co
  4. 中国 ac :bub.Bub65 * a.b
  5. >windows - china * cdef
  6. 小 日本 japen :bub.Bub10 ;;c.e
  7. |
  8. ac ${ } :bub.Bub18
  9. <
  10. ZZ :bub.Bub26
  11. #bub Bub10 m ;;1 小日本
  12. 我之前序号是10
  13.   最后是3
  14. #bub Bub
  15. #bub Bub11 m
  16. 我之前序号是11
  17.   最后是1
  18. #bub Bub 11
  19. #bub Bub18 m ;;6
  20. 我之前序号是18
  21.   最后是4
  22. #bub Bub 4
  23. #bub Bub65 m ;;
  24. 我之前序号是18
  25.   最后是2
  26. '@
  27. $arr = [Collections.ArrayList](($s -split '(?:\r?\n)+#bub Bub\d+ m')[0] -split '\r?\n'); #上半部分
  28. $count = $arr.Count;
  29. $hash = @{};
  30. $global:n = 0;
  31. forEach( $m In [regex]::Matches($s, '(?im)^#bub Bub(\d+) m(?:(?!^#bub Bub\d+ m)[\s\S])+') ){
  32.     $key = $m.Groups[1].Value;  #数字序号
  33.     $value = $m.Groups[0].Value.Trim("`r`n");
  34.     if( !$hash.Contains($key) ){
  35.         $hash.Add( $key, $value );
  36.     }
  37. }
  38. for( $i = 0; $i -lt $count; $i++ ){
  39.     $m = $arr[$i] -match '^([^:]+):bub\.Bub(\d+)';
  40.     if( $m ){
  41.         $arr[$i] = [regex]::Replace($arr[$i], '(?i)(?<=bub\.Bub)\d+',{return (++$global:n)});
  42.         $key = $matches[2];    #数字序号
  43.         if( $hash.Contains($key) ){
  44.             $str = $hash[$key] -replace '(?<=^#bub Bub)\d+ m.*(?=\r?\n)', ('' + $global:n + ' m ;;' + $matches[1]);
  45.         }else{
  46.             $str = '#bub Bub' + $global:n + ' m ;;' + $matches[1] + "`r`n我是新来的";
  47.         }
  48.         [void]$arr.Add( "`r`n" + $str );
  49.     }
  50. }
  51. $arr
复制代码

作者: meixi    时间: 2022-12-3 08:34

本帖最后由 meixi 于 2022-12-3 08:35 编辑

回复 2# WHY
多谢, 我试下面的文本, 序号没有被修改
  1. $s = @'
  2. 字式 $( ) :bub.bub1 * fincc.ic
  3. 字展 ${ } :bub.bub2 * fincc.ic
  4. -
  5. 无环 While :bub.bub3 * fincc.ic
  6. 计环 For :bub.bub4 * fincc.ic
  7. 条循 While :bub.bub5 * fincc.ic
  8. 历循 Foreach :bub.bub6 * fincc.ic
  9. -
  10. 果 if :bub.bub7 * fincc.ic
  11. 则 else :bub.bub8 * fincc.ic
  12. 否果 elseif :bub.bub9 * fincc.ic
  13. 关 switch :bub.bub10 * fincc.ic
  14. 默值 default :bub.bub11 * fincc.ic
  15. |
  16. 到 上 sub :bub.bub13 * fincc.ic
  17. 到 下 sub  :bub.bub14 * fincc.ic
  18. 转换 单 at :bub.bub15 * fincc.ic
  19. 排序 集 at :bub.bub16 * fincc.ic
  20. 排序 项 menu :bub.bub17 * fincc.ic
  21. -
  22. 建 折叠区 region :bub.bub12 * fincc.ic
  23. -
  24. >dows - Cons * fincc.ic
  25. Fi win or conl :m "TO_F dow" * target.ico
  26. -
  27. Fd ac obj :EA_Mai _m * fincc.ic
  28. <
  29. #bub bub1 m
  30. _s.get
  31. _s-"$("
  32. _s+")"
  33. _s.set
  34. #bub bub2 m
  35. _s.get
  36. _s-"${"
  37. _s+"}"
  38. _s.set
  39. '@
复制代码

作者: WHY    时间: 2022-12-3 10:10

回复 3# meixi


    这个样本与顶楼的样本有什么区别,你自己做比较没?
这个样本中 bub.bub 与 #bub bub 是小写,而顶楼给的样本包含大写。
顶楼给出的样本必须具有代表性,改来改去谁都会烦。
作者: WHY    时间: 2022-12-3 10:13

回复 3# meixi


    已修改
作者: 5i365    时间: 2022-12-3 10:27

本帖最后由 5i365 于 2022-12-3 10:50 编辑

回复 4# WHY

多谢指出, 实在不好意思, 描述中忘提了, bub 和Bub 不区分大小写
原来 -match 默认不区分大小写

但 [regex]::Matches 是区分大小写的, 学习了
作者: 5i365    时间: 2022-12-3 10:43

本帖最后由 5i365 于 2022-12-3 10:45 编辑

回复 5# WHY

$s = [io.file]::ReadAllText("C:\Users\Administrator\Desktop\1.txt")
[io.file]::WriteAllLines("C:\Users\Administrator\Desktop\1_ok.txt", $arr)


我把要处理文本用上面的代码外置了,
处理后, 原#开头的行, 后面的换行符变了

作者: WHY    时间: 2022-12-3 11:36

本帖最后由 WHY 于 2022-12-3 11:38 编辑

回复 7# 5i365


    确实,第53行这样改:
  1. $str = $hash[$key] -replace '(?<=^#bub Bub)\d+ m[^\r\n]*', ('' + $global:n + ' m ;;' + $matches[1]);
复制代码
-replace替换运算符中,"."默认可以匹配到\r
作者: 5i365    时间: 2022-12-3 11:40

回复 8# WHY

多谢指教, 惭愧, 对复杂的正则,一看就晕, 先收藏了
作者: 5i365    时间: 2022-12-3 12:15

回复 8# WHY

大侠, 不太明白, .在replace中如果不加(?s)不能匹配到换行吧, 例如下面的代码

  1. $s = @'
  2. 日本
  3. '@
  4. $s -replace '.+人', '外国人' #.没有匹配到换行符
  5. $s -replace '(?s).+人','外国人' #.匹配到了换行符
复制代码

作者: WHY    时间: 2022-12-3 12:57

回复 10# 5i365


    你要是对正则感兴趣,建议你多看看MS官方文档。
https://learn.microsoft.com/zh-c ... regular-expressions
网上关于正则的教程良莠不齐,有的甚至是错误的。

多行模式:修改 ^ 和 $ 的行为,^可以匹配每行的开头,$可以匹配\n(不能匹配\r\n)
单行模式:修改 . 的行为(默认情况下,"."匹配除\n以外的任意字符),可以匹配任意字符,等同于[\s\S]
作者: 5i365    时间: 2022-12-3 13:20

回复 11# WHY
多谢大侠指导,
那默认情况下, 不加  (?s)  或  (?m)

^ 和 $  还有 .


是怎么个匹配情况?  
作者: WHY    时间: 2022-12-3 18:40

11楼的链接你打开过没有?答案就在里面。
https://learn.microsoft.com/zh-c ... ons#default-options
作者: 5i365    时间: 2022-12-3 19:55

回复 13# WHY

多谢,




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