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

[问题求助] PowerShell使用正则将多行文本中的键值整理出来

我想把
sss A=
Key 1
sss Av=
Hello 1
World 1

Av.fff

sss B=
Key 2
sss Bv=
Hello 2

World 2

Bv.fff

sss C=
Key 3
sss Cv=
Hello 3
World 3

Cv.fff

sss kv=
@
{A}={Av}
{B}={Bv}
{C}={Cv}
DDD(kv)

把上面的红色字整理出去,红色字内容是变化的, 但是它所在的位置不变,
整理为:
Key 1
-
Hello 1
World 1
---
Key 2
-
Hello 2

World 2
---
Key 3
-
Hello 3
World 3


键和值之前用 - 分开
键值对儿之间用 --- 分开

写了下面的代码, 遇到了正则匹配问题,

我的想法是用两个括号分别匹配住键和值的内容, 然后再整理, 但是括号就是匹配不上,

请路过大佬支招, 谢谢
  1. $s = @'
  2. sss A=
  3. Key 1
  4. sss Av=
  5. Hello 1
  6. World 1
  7. Av.fff
  8. sss B=
  9. Key 2
  10. sss Bv=
  11. Hello 2
  12. World 2
  13. Bv.fff
  14. sss C=
  15. Key 3
  16. sss Cv=
  17. Hello 3
  18. World 3
  19. Cv.fff
  20. sss kv=
  21. @
  22. {A}={Av}
  23. {B}={Bv}
  24. {C}={Cv}
  25. DDD(kv)
  26. '@
  27. $rx = [regex]'sss [A-Z]=\r\n(.+)\r\nsss [A-Z]v=(?s)(.+)?[A-Z]v.fff'
  28. $rx.Matches($s).Value
复制代码

  1. sss A=
  2. Key 1
  3. sss Av=
  4. Hello 1
  5. World 1
  6. Av.fff
  7. sss B=
  8. Key 2
  9. sss Bv=
  10. Hello 2
  11. World 2
  12. Bv.fff
  13. sss C=
  14. Key 3
  15. sss Cv=
  16. Hello 3
  17. World 3
  18. Cv.fff
  19. sss kv=
  20. @
  21. {A}={Av}
  22. {B}={Bv}
  23. {C}={Cv}
  24. DDD(kv)
复制代码
以ANSI格式保存为1.txt
  1. /sss [^ ]=/ {
  2. A = substr($0, 1, 5) "v="
  3. B = substr($0, 5, 1) "v.fff"
  4. while ((getline) > 0) {
  5. if ($0 == B) {
  6. print "---"
  7. next
  8. }
  9. if ($0 == A) {
  10. print "-"
  11. } else {
  12. print
  13. }
  14. }
  15. }
复制代码
以ANSI格式保存为1.awk
下载gawk( http://bcn.bathome.net/tool/4.1.0/gawk.exe
执行
  1. gawk -f.\1.awk 1.txt>2.txt
复制代码
结果(2.txt)
  1. Key 1
  2. -
  3. Hello 1
  4. World 1
  5. ---
  6. Key 2
  7. -
  8. Hello 2
  9. World 2
  10. ---
  11. Key 3
  12. -
  13. Hello 3
  14. World 3
  15. ---
复制代码
1

评分人数

TOP

回复 2# hfxiang


    多谢大佬支招,

好像没有用正则, 这个exe能支持管道吗? 也就是要处理的文本不是在文件中获取

TOP

本帖最后由 xczxczxcz 于 2022-11-20 14:35 编辑

娱乐一下:
  1. $s = @'
  2. sss A=
  3. Key 1
  4. sss Av=
  5. Hello 1
  6. World 1
  7. Av.fff
  8. sss B=
  9. Key 2
  10. sss Bv=
  11. Hello 2
  12. World 2
  13. Bv.fff
  14. sss C=
  15. Key 3
  16. sss Cv=
  17. Hello 3
  18. World 3
  19. Cv.fff
  20. sss kv=
  21. @
  22. {A}={Av}
  23. {B}={Bv}
  24. {C}={Cv}
  25. DDD(kv)
  26. '@
  27. [regex]::Replace($s, "(?sm)(?:(?!Key).)*Key\s*(\d+)(?:(?!\w+\s*\1).)*(?<m>(?:(?!\r?\n\s*\w+v\.fff).)*)","Key `$1`r`n-`r`n`${m}`r`n---`r`n") -replace '(?s)\r?\n?\s*(---)(?:(?!\1).)*$' -replace '(?m)^ +(\w+)','$1';
  28. ([regex]::Matches($s,"(?is)Key(?:(?!\r?\n?\w+v\.fff).)*").Value -join "`r`n---`r`n") -replace '(?m)(?:(?!v=).)*v=','-' -replace '(?m)^ +(\w+)','$1';
  29. 或 自己弄
复制代码
1

评分人数

QQ: 己阵亡
脚本优先 [PowerShell win10]

TOP

本帖最后由 小白龙 于 2022-11-20 15:37 编辑

回复 4# xczxczxcz


  多谢大佬支招,

对正则有点晕, 有个情况忘提了,
处理前: 所有键的内容和值的内容的每行前都有一个空格,
处理后: 要删除所有键和值的内容的每行前的空格

现在下面键值内部的空行前面还是有个空格

sss Bv=
Hello 2

World 2
Bv.fff

TOP

回复 4# xczxczxcz


   不好意思大佬, 我前面的描述太粗略了, 实际我想表达的是下面这个贴子的反向整理

http://www.bathome.net/thread-64359-1-1.html

TOP

正则非常通用呀,用多就会了
  1. $s -replace '(?s)sss (?<a>.)=\s*(.+)\s*sss (\k<a>)v=\s*(.+)\s*(\k<a>)v.fff\s*',"`$1-`r`n`$3---`r`n" -replace '(?s)\s*---\s*sss kv=.+|(?m)^ +'
复制代码
1

评分人数

TOP

回复 7# idwma

大佬666,

说实话, 您写的这正则, 我一看就晕了

TOP

本帖最后由 小白龙 于 2022-11-20 18:47 编辑

回复 7# idwma


大佬请教一下

(?s)
这个是什么意思? 是单行模式吗? 我记得有的地方还说, 这是打开 .匹配空白符的模式

<a>
这个什么意思, 没见过

\k
是什么

我敢说, 没有几年功力, 真写不出您这正则, 真是看不懂

TOP

回复 9# 小白龙

文档里都有说明呀,看不懂的地方多搜点例子多看几个就会了
  1. https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/regular-expression-language-quick-reference
复制代码

TOP

回复 4# xczxczxcz


   大佬,  能请教一下吗? 下面这两行什么意思, 我powershell官网搜索也没有找到, 只有(?m) (?s)

(?sm)

(?is)

TOP

回复 10# idwma


   多谢大侠的链接, 以前在PS官网真没找到这么细的资料

TOP

本帖最后由 小白龙 于 2022-11-21 20:34 编辑

回复 7# idwma


    大佬你好, 看了正则的资料后, 对(?s)还是搞不懂, 按理说, 它是放在正则前面的, 表示单行模式,

但是下面的例子中, 它是放在中间的,很少有资料介绍到这种情况

零星的资料解释说, 这是让.能匹配到\s空字符了
更搞不明白的是, 4楼的大佬, 正则的开头出现了(?sm) 这是什么意思, 单行和多行模式还能混在一起玩吗?
  1. $s = @'
  2. public static
  3. {
  4. #if A
  5.     part1
  6. #endif
  7. part
  8. part
  9. #if V
  10.     part2
  11. #endif
  12. part
  13. part
  14. #if C
  15.     part3
  16. #endif
  17. }
  18. '@
  19. $rx = [regex]'#if.*(?s)(.*?)#endif'
  20. $rx.Matches($s) |
  21. %{
  22. $_.Groups[1].Value
  23. }
复制代码

TOP

回复 13# 小白龙

正则用法灵活呀,不用过于纠结合不合理

TOP

回复 7# idwma


  大佬, 不用 (\k<a>) 这个方法可以实现吗? 这个正则我在另一个软件中, 它不支持这个特性, 只支持 $1 $2 这种数字格式

TOP

返回列表