Board logo

标题: [问题求助] 用Powershell 正则替换标签内容 [打印本页]

作者: 5i365    时间: 2022-6-1 17:36     标题: 用Powershell 正则替换标签内容

我想把下面红色字部分,替换为 <abc> 使用下面代码中的正则,会删掉粉色字的部分, 求路过高手指引, 提前感谢!
(gc 0.txt) -replace '(?s)(?<=<div id="topic_panel.*?>).*(?=</div>)', '<abc>' | Out-File ok.txt

-----------------------------------------------------------------------------------------------0.txt

    <div id="topic_panel" style="display: none">
        <div class="p_div"><p>Insert</p></div>
        <ul>
            <li id="sub-topic" class="submenu_btn"><span>A</label></span></li>
        </ul>

    </div>
    </div>
    <div id="transform_panel" style="display: none">
        <ul>
            <li id="clear_transform" class="submenu_btn" data-action="reset"><span>Reset Rotation/Skew</span></li>
            <li id="rotate_left" class="submenu_btn" data-action="rotate-left"><span>Rotate Left</span></li>
            <li id="rotate_right" class="submenu_btn" data-action="rotate-right"><span>Rotate Right</span></li>
            <li id="skew_left" class="submenu_btn" data-action="skew-left"><span>Skew Left</span></li>
            <li id="skew_right" class="submenu_btn" data-action="skew-right"><span>Skew Right</span></li>
        </ul>
    </div>

作者: flashercs    时间: 2022-6-2 07:25

本帖最后由 flashercs 于 2022-6-2 21:06 编辑
  1. function Get-AngleNode {
  2.     [CmdletBinding()]
  3.     [OutputType('System.Text.RegularExpressions.Match')]
  4.     param(
  5.         [Parameter(Mandatory = $true)]
  6.         [string]$Html,
  7.         # MUST like "<(?<openTag>[\w.:-]+)[^>]*>"
  8.         [Parameter(mandatory = $true)]
  9.         [regex]$ReAngle,
  10.         # To find all nodes
  11.         [switch]$FindAll
  12.     )
  13.     $startPosition = 0
  14.     $reTag = [regex]'</(?<closeTag>[\w.:-]+)>|<(?<openTag>[\w.:-]+)[^>]*>'
  15.     $stackTag = New-Object 'System.Collections.Generic.Stack[string]'
  16.     do {
  17.         $m = $ReAngle.Match($Html, $startPosition)
  18.         if ($m.Success) {
  19.             $m #openTag
  20.             $stackTag.Push($m.Groups['openTag'].Value)
  21.             $startPosition = $m.Index + $m.Length
  22.             while ($true) {
  23.                 $m = $reTag.Match($Html, $startPosition)
  24.                 if (-not $m.Success) { break }
  25.                 $startPosition = $m.Index + $m.Length
  26.                 if ($m.Groups['openTag'].Success) {
  27.                     $stackTag.Push($m.Groups['openTag'].Value)
  28.                 } elseif ($stackTag.Peek() -eq $m.Groups['closeTag'].Value) {
  29.                     $null = $stackTag.Pop()
  30.                     if ($stackTag.Count -eq 0) {
  31.                         $m #clostTag
  32.                         break
  33.                     }
  34.                 } else { $PSCmdlet.WriteWarning("html parsing error: Index=$($m.Groups['closeTag'].Index),Value=$m") }
  35.             }
  36.         } else { break }
  37.     }while ($FindAll)
  38. }
  39. function Edit-HtmlNode {
  40.     [CmdletBinding()]
  41.     [OutputType('string')]
  42.     param(
  43.         [Parameter(Mandatory = $true)]
  44.         [string]$Html,
  45.         [Parameter(Mandatory = $true)]
  46.         [System.Collections.IDictionary]$DicNode
  47.     )
  48.     $strb = New-Object System.Text.StringBuilder
  49.     $newhtml = $Html
  50.     foreach ($key in $DicNode.Keys) {
  51.         $null = $strb.Clear()
  52.         $arrM = Get-AngleNode -Html $newhtml -ReAngle $key -FindAll
  53.         $index = 0
  54.         foreach ($m in $arrM) {
  55.             if ($m.Groups['openTag'].Success) {
  56.                 $null = $strb.Append($newhtml, $index, $m.Index + $m.Length - $index)
  57.             } else {
  58.                 $null = $strb.Append($DicNode[$key]).Append($m.Value)
  59.             }
  60.             $index = $m.Index + $m.Length
  61.         }
  62.         $null = $strb.Append($newhtml.Substring($index))
  63.         $newhtml = $strb.ToString()
  64.     }
  65.     $newhtml
  66. }
  67. # region config
  68. $html = @"
  69. <div>
  70. <div id="topic_panel" style="display: none">
  71.         <div class="p_div"><p>Insert</p></div>
  72.         <ul>
  73.             <li id="sub-topic" class="submenu_btn"><span>A</label></span></li>
  74.         </ul>
  75.     </div>
  76.     </div>
  77.     <h1 id="to_cd">-------------------------------------</h1>
  78.     <div id="transform_panel" style="display: none">
  79.         <ul>
  80.             <li id="clear_transform" class="submenu_btn" data-action="reset"><span>Reset Rotation/Skew</span></li>
  81.             <li id="rotate_left" class="submenu_btn" data-action="rotate-left"><span>Rotate Left</span></li>
  82.             <li id="rotate_right" class="submenu_btn" data-action="rotate-right"><span>Rotate Right</span></li>
  83.             <li id="skew_left" class="submenu_btn" data-action="skew-left"><span>Skew Left</span></li>
  84.             <li id="skew_right" class="submenu_btn" data-action="skew-right"><span>Skew Right</span></li>
  85.         </ul>
  86.         <div id="top_ab" class="p_div"><p>Insert</p></div>
  87.     </div>
  88. "@
  89. $htNode = @{
  90.     '(?i)<(?<openTag>div) id="topic_panel"[^>]*>' = '<abc>text</abc>'
  91.     '(?i)<(?<openTag>div) id="top_ab"[^>]*>'      = '<a>tet</a>'
  92.     '(?i)<(?<openTag>H1) id="to_cd"[^>]*>'        = '<b>xt</b>'
  93. }
  94. $newhtml = Edit-HtmlNode -Html $html -DicNode $htNode
  95. $newhtml
复制代码

作者: 5i365    时间: 2022-6-2 09:14

本帖最后由 5i365 于 2022-6-2 09:34 编辑

回复 2# flashercs


可以得到正常的输出, 非常感谢大侠指引!
当需要查找的标签有N个, 分别替换成不同内容, 代码需要怎样更改? 实在看不懂代码含义 例如有3个需要查找和替换的标签及内容, 写在了下面的Hash中了
@{

'div id="topic_panel"' = '<abc>text</abc>'

'div id="top_ab"' = '<a>tet</a>'

'H1 id="to_cd"' = '<b>xt</b>'
}


看来直接正则替换的方法行不通了...
作者: idwma    时间: 2022-6-2 10:57

突然看懂了那个正则闭合标签的例子
  1. (gc 0.txt) -join "`n" -replace '(?s)(<(?<HtmlTag>div) id=\"topic_panel.*?>)((?<Nested><\k<HtmlTag>[^>]*>)|</\k<HtmlTag>>(?<-Nested>)|.*?)*(</\k<HtmlTag>>)','$1<abc>$3'
复制代码

作者: flashercs    时间: 2022-6-2 21:10

本帖最后由 flashercs 于 2022-6-4 20:02 编辑

回复 4# idwma


    感谢分享,我不知道.NET正则支持递归查询,还傻傻地自己造轮子.
  1. function Edit-HtmlNode {
  2.   [CmdletBinding()]
  3.   [OutputType('string')]
  4.   param(
  5.     [Parameter(Mandatory = $true)]
  6.     [string]$Html,
  7.     [Parameter(Mandatory = $true)]
  8.     [System.Collections.IDictionary]$DicNode
  9.   )
  10.   $dic = New-Object 'System.Collections.Generic.Dictionary[string,string]'
  11.   foreach ($key in $DicNode.Keys) {
  12.     $dic[$key + '(?is)[^<>]*(?>(?>(?:<!--.*?-->|<script[^>]*>.*?</script>|<input[^>]*>|<br[^>]*>|<img[^>]*>|<link[^>]*>|<meta[^>]*>|<!DOCTYPE[^>]*>|(?<node><(?<nodeName>[\w.:-]+)[^>]*>))[^<>]*)+(?>(?<-node></(?<-nodeName>\k<nodeName>)>)[^<>]*)*)*(</\k<openTag>>)'] = $DicNode[$key]
  13.   }
  14.   $newhtml = $Html
  15.   foreach ($key in $dic.Keys) {
  16.     $newhtml = $newhtml -replace $key, ('${1}' + $dic[$key] + '${2}')
  17.   }
  18.   $newhtml
  19. }
  20. # region config
  21. $html = Get-Content -LiteralPath $PSScriptRoot\test1.html -Raw -Encoding UTF8
  22. # endregion
  23. $htNode = @{
  24.   '(?is)(<(?<openTag>div) id="topic_panel"[^>]*>)' = '1'
  25.   '(?is)(<(?<openTag>div) id="top_ab"[^>]*>)'      = '<a>tet</a>'
  26.   '(?is)(<(?<openTag>H1) id="to_cd"[^>]*>)'        = '<b>xt</b>'
  27.   '(?is)(<(?<openTag>div) id="topic_shapes_panel"[^>]*>)' = ''
  28. }
  29. $newhtml = Edit-HtmlNode -Html $html -DicNode $htNode
  30. $newhtml
复制代码

作者: 5i365    时间: 2022-6-2 22:32

本帖最后由 5i365 于 2022-6-2 22:34 编辑

回复 5# flashercs


   试了几个文件, 发现两个小问题1.对下图结构的标签, 不能完整替换, 我想将粉框中的内容替换为空   '(?is)(<(?<openTag>div) id="topic_shapes_panel"[^>]*>)'        = ''



2.如果替换为数字,例如1 好像把所有的都删了  '(?is)(<(?<openTag>div) id="topic_panel"[^>]*>)'        = '1'
作者: flashercs    时间: 2022-6-2 22:49

本帖最后由 flashercs 于 2022-6-2 22:59 编辑

回复 6# 5i365


    看清了.目测 没问题的.可以把这部分html发出来看看
修改html 不太建议用正则,可以使用.NET库 htmlAgility
作者: 5i365    时间: 2022-6-2 23:08

本帖最后由 5i365 于 2022-6-2 23:14 编辑

回复 7# flashercs


   感谢大侠回复,
我是用下面方法加载的html, 不加-raw好像没效果,
$html = gc 9.html -enc utf8 -raw
上面贴子图片的中的内容
https://send.cm/d/BrWp
作者: flashercs    时间: 2022-6-2 23:16

回复 8# 5i365


    5楼代码改了一下; $html=gc $file -raw -enc utf8 对了,html是一个字符串;不是string[]
作者: 5i365    时间: 2022-6-2 23:29

回复 9# flashercs


   奇怪, 这回替换没有动静了
作者: flashercs    时间: 2022-6-4 20:03

回复 10# 5i365


    5楼 修改了一下.看看
作者: 5i365    时间: 2022-6-6 16:00

回复 11# flashercs


   感谢大侠回复, 应该可以了!




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