返回列表 发帖

[问题求助] 用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 21:06 编辑
function Get-AngleNode {
    [CmdletBinding()]
    [OutputType('System.Text.RegularExpressions.Match')]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Html,
        # MUST like "<(?<openTag>[\w.:-]+)[^>]*>"
        [Parameter(mandatory = $true)]
        [regex]$ReAngle,
        # To find all nodes
        [switch]$FindAll
    )
    $startPosition = 0
    $reTag = [regex]'</(?<closeTag>[\w.:-]+)>|<(?<openTag>[\w.:-]+)[^>]*>'
    $stackTag = New-Object 'System.Collections.Generic.Stack[string]'
    do {
        $m = $ReAngle.Match($Html, $startPosition)
        if ($m.Success) {
            $m #openTag
            $stackTag.Push($m.Groups['openTag'].Value)
            $startPosition = $m.Index + $m.Length
            while ($true) {
                $m = $reTag.Match($Html, $startPosition)
                if (-not $m.Success) { break }
                $startPosition = $m.Index + $m.Length
                if ($m.Groups['openTag'].Success) {
                    $stackTag.Push($m.Groups['openTag'].Value)
                } elseif ($stackTag.Peek() -eq $m.Groups['closeTag'].Value) {
                    $null = $stackTag.Pop()
                    if ($stackTag.Count -eq 0) {
                        $m #clostTag
                        break
                    }
                } else { $PSCmdlet.WriteWarning("html parsing error: Index=$($m.Groups['closeTag'].Index),Value=$m") }
            }
        } else { break }
    }while ($FindAll)
}
function Edit-HtmlNode {
    [CmdletBinding()]
    [OutputType('string')]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Html,
        [Parameter(Mandatory = $true)]
        [System.Collections.IDictionary]$DicNode
    )
    $strb = New-Object System.Text.StringBuilder
    $newhtml = $Html
    foreach ($key in $DicNode.Keys) {
        $null = $strb.Clear()
        $arrM = Get-AngleNode -Html $newhtml -ReAngle $key -FindAll
        $index = 0
        foreach ($m in $arrM) {
            if ($m.Groups['openTag'].Success) {
                $null = $strb.Append($newhtml, $index, $m.Index + $m.Length - $index)
            } else {
                $null = $strb.Append($DicNode[$key]).Append($m.Value)
            }
            $index = $m.Index + $m.Length
        }
        $null = $strb.Append($newhtml.Substring($index))
        $newhtml = $strb.ToString()
    }
    $newhtml
}
# region config
$html = @"
<div>
<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>
    <h1 id="to_cd">-------------------------------------</h1>
    <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 id="top_ab" class="p_div"><p>Insert</p></div>
    </div>
"@
$htNode = @{
    '(?i)<(?<openTag>div) id="topic_panel"[^>]*>' = '<abc>text</abc>'
    '(?i)<(?<openTag>div) id="top_ab"[^>]*>'      = '<a>tet</a>'
    '(?i)<(?<openTag>H1) id="to_cd"[^>]*>'        = '<b>xt</b>'
}
$newhtml = Edit-HtmlNode -Html $html -DicNode $htNode
$newhtmlCOPY
1

评分人数

    • 5i365: 技术牛X, 乐于分享技术 + 1
微信:flashercs
QQ:49908356

TOP

本帖最后由 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>'
}


看来直接正则替换的方法行不通了...
本人所发所有贴子或代码, 诸大侠若认为有改进之处,请不吝赐教,感激不尽!

TOP

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

评分人数

TOP

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

回复 4# idwma


    感谢分享,我不知道.NET正则支持递归查询,还傻傻地自己造轮子.
function Edit-HtmlNode {
  [CmdletBinding()]
  [OutputType('string')]
  param(
    [Parameter(Mandatory = $true)]
    [string]$Html,
    [Parameter(Mandatory = $true)]
    [System.Collections.IDictionary]$DicNode
  )
  $dic = New-Object 'System.Collections.Generic.Dictionary[string,string]'
  foreach ($key in $DicNode.Keys) {
    $dic[$key + '(?is)[^<>]*(?>(?>(?:<!--.*?-->|<script[^>]*>.*?</script>|<input[^>]*>|<br[^>]*>|<img[^>]*>|<link[^>]*>|<meta[^>]*>|<!DOCTYPE[^>]*>|(?<node><(?<nodeName>[\w.:-]+)[^>]*>))[^<>]*)+(?>(?<-node></(?<-nodeName>\k<nodeName>)>)[^<>]*)*)*(</\k<openTag>>)'] = $DicNode[$key]
  }
  $newhtml = $Html
  foreach ($key in $dic.Keys) {
    $newhtml = $newhtml -replace $key, ('${1}' + $dic[$key] + '${2}')
  }
  $newhtml
}
# region config
$html = Get-Content -LiteralPath $PSScriptRoot\test1.html -Raw -Encoding UTF8
# endregion
$htNode = @{
  '(?is)(<(?<openTag>div) id="topic_panel"[^>]*>)' = '1'
  '(?is)(<(?<openTag>div) id="top_ab"[^>]*>)'      = '<a>tet</a>'
  '(?is)(<(?<openTag>H1) id="to_cd"[^>]*>)'        = '<b>xt</b>'
  '(?is)(<(?<openTag>div) id="topic_shapes_panel"[^>]*>)' = ''
}
$newhtml = Edit-HtmlNode -Html $html -DicNode $htNode
$newhtmlCOPY
1

评分人数

    • 5i365: 技术牛X, 乐于分享技术 + 1
微信:flashercs
QQ:49908356

TOP

本帖最后由 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'
本人所发所有贴子或代码, 诸大侠若认为有改进之处,请不吝赐教,感激不尽!

TOP

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

回复 6# 5i365


    看清了.目测 没问题的.可以把这部分html发出来看看
修改html 不太建议用正则,可以使用.NET库 htmlAgility
微信:flashercs
QQ:49908356

TOP

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

回复 7# flashercs


   感谢大侠回复,
我是用下面方法加载的html, 不加-raw好像没效果,
$html = gc 9.html -enc utf8 -raw
上面贴子图片的中的内容
https://send.cm/d/BrWp
本人所发所有贴子或代码, 诸大侠若认为有改进之处,请不吝赐教,感激不尽!

TOP

回复 8# 5i365


    5楼代码改了一下; $html=gc $file -raw -enc utf8 对了,html是一个字符串;不是string[]
微信:flashercs
QQ:49908356

TOP

回复 9# flashercs


   奇怪, 这回替换没有动静了
本人所发所有贴子或代码, 诸大侠若认为有改进之处,请不吝赐教,感激不尽!

TOP

回复 10# 5i365


    5楼 修改了一下.看看
微信:flashercs
QQ:49908356

TOP

回复 11# flashercs


   感谢大侠回复, 应该可以了!
本人所发所有贴子或代码, 诸大侠若认为有改进之处,请不吝赐教,感激不尽!

TOP

返回列表