找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 14188|回复: 4

[问题求助] [已解决]Powershell中定义函数可根据不同参数处理不同区域

[复制链接]
发表于 2022-12-17 15:42:10 | 显示全部楼层 |阅读模式
本帖最后由 meixi 于 2022-12-21 07:41 编辑

我需要在Powershell中定义一个函数, 它可以根据不同的参数来处理文本文件中的不同区域
下面图片是一个示意图,  它标记了要处理的文本的不同区域

区域用A和B两个标记(即:一行开头的文本)来划分:
若一行以A标记的文本开头, 则是区域的开始
若一行以B标记的文本开头, 则是区域的结尾
所以上图中有两个要处理的区域, 分别是①区和②区

函数的构造如下:
函数名: GetTextArea
参数可以有3个或2个
-----------------------------------------------------------------------------------
当参数有3个时:   
函数表达式是:   GetTextArea -A "SSSS=" -B "MMM" -C $SortLine
同时存在标记参数-A和-B 例如上图中
        -A参数的值是 SSSS=
        -B参数的值是 MMM
还存在参数-C
        这个参数是一段代码段的变量名 $SortLine (代码来自下面的链接,感谢iD大佬)
        http://www.bathome.net/thread-64701-1-1.html
        它的作用是分别排序前面-A和-B两个标记所获取的区域中的文本, 即图中①区和②区的文本
函数的最后输出值, 是-C代码处理①区和②区后的文本替换原始文本后的整个文本
-----------------------------------------------------------------------------------
当参数有2个时, 分两种情况:
★情况一
函数表达式是:   GetTextArea -A "SSSS=" -C $SortLine
只有参数-A 但没有参数-B 例如上图中, 有-A参数: 值是 SSSS=
还存在参数-C
此情况下, 函数的输出值, 是-C中的代码只处理第1个-A标记之前的文本(绿框中的文本)后的内容

★情况二
函数表达式是:   GetTextArea -B "MMM" -C $SortLine
只有参数-B 但没有参数-A 例如上图中, 有-B参数: 值是 MMM
还存在参数-C
此情况下, 函数的输出值, 是参数-C中的代码只处理最后一个-B标记之后的文本(粉框中的文本)后的内容
  1. $SortLine = {
  2.         $a = @(0)
  3.         $s -split '\n' | %{
  4.                 if ($_ -match '^\D*\d+')
  5.                 {
  6.                         $a[-1] += 1
  7.                         $_ -replace '(?<=^\D*)\d+', ($a -join '')
  8.                 }
  9.                 else { $_ }
  10.                 if ($_ -match '^\s*\)') { $a += 0 }
  11.                 if ($_ -match '^\s*\(') { $a = $a[0 .. ($a.count - 1 - 1)] }
  12.         }
  13. }
复制代码
上图中的文本测试文件
  1. @'
  2. 1 中间
  3. -
  4. 3 日
  5. -
  6. 9 韩
  7. SSSS=
  8. 1 中间
  9. -
  10. 3 日
  11. -
  12. 1 美丽
  13. MMM
  14. abc
  15. bcd
  16. abc
  17. SSSS=
  18. 6 日
  19. 9 中
  20. ) 13 好
  21.         43 日
  22.         ) 43 子
  23.                 02 大家
  24.                 82 中
  25.         (
  26. (
  27. -
  28. 1 日
  29. MMM
  30. 6 日
  31. ) 13 好
  32.         43 日
  33.         ) 43 子
  34.                 82 中
  35.         (
  36.         43 华
  37.         -
  38.         72 行人
  39. (
  40. -
  41. 1 日
  42. '@ | Out-File 1.txt -enc utf8
复制代码

评分

参与人数 1PB +2 收起 理由
Batcher + 2 感谢给帖子标题标注[已解决]字样

查看全部评分

 楼主| 发表于 2022-12-17 15:51:25 | 显示全部楼层
和下面这个链接中的处理方式类似
http://www.bathome.net/viewthread.php?tid=62151&highlight=
发表于 2022-12-18 20:17:26 | 显示全部楼层
  1. $SortLine = {
  2.         $a = @(0)
  3.         $b=$args[0] -split '\n' | %{
  4.                 if ($_ -match '^\D*\d+')
  5.                 {
  6.                         $a[-1] += 1
  7.                         $_ -replace '(?<=^\D*)\d+', ($a -join '')
  8.                 }
  9.                 else { $_ }
  10.                 if ($_ -match '^\s*\)') { $a += 0 }
  11.                 if ($_ -match '^\s*\(') { $a = $a[0 .. ($a.count - 1 - 1)] }
  12.         }
  13.         $b -join "`n"
  14. }

  15. function GetTextArea($A,$B,$C,$s=(gc 1.txt) -join "`n"){
  16. if($A -and $B -and $C){[regex]::replace($s,"(?s)(?<=$A\s+)(?<AB>.*?)(?=\s+$B)",{&$C $args[0].groups['AB'].value})}
  17. elseif($A -and $C){[regex]::replace($s,"(?s)^(?<A>.*?)(?=\s*$A)",{&$C $args[0].groups['A'].value})}
  18. elseif($B -and $C){[regex]::replace($s,"(?s)(^.+$B\s+)(?<B>.*)",{$args[0].groups[1].value;&$C $args[0].groups['B'].value})}
  19. }
复制代码
 楼主| 发表于 2022-12-19 18:28:27 | 显示全部楼层
本帖最后由 meixi 于 2022-12-19 18:53 编辑

回复 3# idwma


  多谢大佬,

不好意思, 上面描述丢了点东西, 就是定义的函数要处理的文本, 是从前面的管道流来的! 例如像下面这样的格式, 这样就完美了
在哪里看到过, 好像要在函数体内添加$input变量的处理逻辑就可以了

gc 1.txt -enc UTF8 | GetTextArea -A "SSSS=" -B "MMM" -C $SortLine | Out-File 1_ok.txt -enc UTF8

另外还发现一个小问题,
处理后的文本, 换行符都变成了LF, 只有最后一行换行符是CRLF

用notepad2打开后, 直接提示换行符不统一,
应该win下都是CRLF
发表于 2022-12-19 19:48:45 | 显示全部楼层
  1. function GetTextArea($A,$B,$C){
  2. $ofs="`r`n"
  3. $s="$input"
  4. if($A -and $B -and $C){[regex]::replace($s,"(?s)(?<=$A\s+)(?<AB>.*?)(?=\s+$B)",{&$C $args[0].groups['AB'].value})}
  5. elseif($A -and $C){[regex]::replace($s,"(?s)^(?<A>.*?)(?=\s*$A)",{&$C $args[0].groups['A'].value})}
  6. elseif($B -and $C){[regex]::replace($s,"(?s)(^.+$B\s+)(?<B>.*)",{$args[0].groups[1].value+(&$C $args[0].groups['B'].value)})}
  7. }
复制代码

评分

参与人数 1技术 +1 收起 理由
meixi + 1 乐于助人

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 01:12 , Processed in 0.021819 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表