【问题标题】:Replace special characters in multiple strings between two strings in PowerShell在PowerShell中的两个字符串之间替换多个字符串中的特殊字符
【发布时间】:2014-09-14 13:54:18
【问题描述】:

背景:我将 .mp4 视频的文件名更改为小写,并替换了特殊字符和空格。现在我必须以类似的方式更改 .txt 文件中的关联 URL。有许多文本文件包含大量引用视频的这些 URL。

问题:我应该替换任何文本文件中“flashplayer”和“/flashplayer”之间的每个字符串中的特殊字符,但不得更改flashplayer 标签之外的任何内容。

我不知道如何选择“flashplayer”和“/flashplayer”之间的字符串进行替换。

示例字符串:

(flashplayer width="640" height="480" position="1")file=/wiki/data/media/sales/a/ö 2.mp4&config=/wiki/lib/plugins/flashplayer/config_video.xml&start=0(/flashplayer)

此示例包含在文本文件(DokuWiki 页面)中。 () 表示标记字符。

示例输出字符串:

(flashplayer width="640" height="480" position="1")file=/wiki/data/media/sales/a/oe_2.mp4&config=/wiki/lib/plugins/flashplayer/config_video.xml&start=0(/flashplayer)

rename-item 的替换应该是:

  • ä = ae
  • ö = oe
  • ü = ue
  • ' ' = '_'

更新: 脚本如下:

# vars (User-Eingabe)
$source = "d:\here\name\test\pages"
$search = '(\<flashplayer.*?\>file\=/wiki/87sj38d/media)(.*?)(\<\/flashplayer\>)'
$a = 1
Write-Host "`nSource:`t $source`n"
# replace special characters
gci $source -r -Filter *.txt | ForEach-Object {
    $text = Get-Content $_.FullName | ForEach-Object {
        if($_ -match $search) {
            $_ -replace [Regex]::Escape($Matches[2]), ($Matches[2] -replace'ö', 'oe' -replace'ä', 'ae' -replace'ü', 'ue' -replace'\s', '_' )
            $output = $Matches[2]
            $tags = $a++         
            Write-Host "`nTag $tags : $output"
        } else {
            $_
        }
    }
    $text | Set-Content $_.FullName
}

文本文件包含这样一行代码:

{{backlinks>path:product:description:kennwort_aendern}}

脚本只有在我删除这行代码时才有效。否则 flashplayertags 之间的字符串保持不变。令人困惑的是,替换有时会起作用,有时不会。 flashplayertags 之间的字符串可以包含许多特殊字符。查看示例字符串:

<flashplayer_width="640"_height="480"_position="1">file=/wiki/87sj38d/media/ab/any/test/1001_Grundlagen Kennwort ändern.mp4&image=/wiki/87sj38d/media/ab/any/test/1001_Grundlagen Kennwort ändern.jpg&config=/wiki/lib/plugins/flashplayer/config_video.xml&start=0</flashplayer>

Write-Host $output 正确显示所有字符串,但替换功能不正常。

【问题讨论】:

  • 您也可以发布任何示例字符串吗?
  • 您能否也添加一个必需的输出字符串?
  • 现在问题包含一个示例。谢谢

标签: string powershell character-replacement


【解决方案1】:

这里有可以用来替换上述字符的命令。您将需要根据文本文件的位置更改文件路径。 Replace-FileString.ps1 被使用; http://windowsitpro.com/scripting/replacing-strings-files-using-powershell

./Replace-FileString  -Pattern '(flashplayer)(.*)ä(.*)(\/flashplayer)'  -Replacement '$1$2ae$3$4'  -Path C:\test\*.txt  -Overwrite
./Replace-FileString  -Pattern '(flashplayer)(.*)ö(.*)(\/flashplayer)'  -Replacement '$1$2oe$3$4'  -Path C:\test\*.txt  -Overwrite
./Replace-FileString  -Pattern '(flashplayer)(.*)ü(.*)(\/flashplayer)'  -Replacement '$1$2ue$3$4'  -Path C:\test\*.txt  -Overwrite
./Replace-FileString  -Pattern '(flashplayer)(.*) (.*)(\/flashplayer)'  -Replacement '$1$2_$3$4'  -Path C:\test\*.txt  -Overwrite

它打开并写入所有文本文件(即使它没有改变任何东西)。它只会更改字符串“flashplayer”和“/flashplayer”之间存在“ä”、“ö”、“ü”或“”的行。

【讨论】:

    【解决方案2】:

    你可以试试这样的。对于每个文本文件,它将替换每个 flashplayer 行上的特殊字符。

    Get-ChildItem -Path "c:\FolderOfTextfiles" -Filter *.txt | ForEach-Object {
    
        $text = Get-Content $_.FullName | ForEach-Object {
            if($_ -match '(?<=\(flashplayer.*?\))(.*?)(?=\(/flashplayer\))') {
                $_ -replace [Regex]::Escape($Matches[1]), ($Matches[1] -replace'ö', 'oe' -replace 'ä', 'ae' -replace 'ü', 'ue' -replace '\s', '_' )
            } else {
                $_
            }
        }
    
        $text | Set-Content $_.FullName
    
    }
    

    更新:如果文本包含换行符,那么您可以尝试这个全局多行正则表达式匹配方法:

    $s = @'
    <flashplayer_width="640"_height="480"_position="1">file=/wiki/87sj38d/media/ab/any/test/1001_Grundlagen Kennwort ändern.mp4&image=/wiki/87sj38d/media/ab/
    any/test/1001_Grundlagen Kennwort ändern.jpg&config=/wiki/lib/plugins/flashplayer/config_video.xml&start=0</flashplayer>
    <flashplayer_width="640"_height="480"_position="1">file=/wiki/87sj38f/media/ab/any/test/1001_Grundlagen Kennwort ändern.mp4&image=/wiki/87sj38d/media/ab/any/test/1001_Grundlagen Kennwort ändern.jpg&
    config=/wiki/lib/plugins/flashplayer/config_video.xml&start=0</flashplayer>
    '@
    
    #Read text as single string
    #PS 3.0+
    #$s = Get-Content .\test.txt -Raw
    
    #PS 2.0
    #$s = Get-Content .\test.txt | Out-String
    
    $s = [regex]::Replace($s, '(?s)(?<=<flashplayer.*?>file=/wiki/87sj38d/media).*?(?=</flashplayer>)', { 
        param([System.Text.RegularExpressions.Match]$m)
        $m.Value -replace 'ö', 'oe' -replace 'ä', 'ae' -replace 'ü', 'ue' -replace ' ', '_'
    })
    
    $s    
    
    #Save
    #$s | Set-Content .\test.txt
    

    这是一个更复杂的解决方案,因为在当前 PowerShell 版本中使用 -replace 'pattern', '$1' 时,您无法修改 $1(捕获的组)。如果有人有更好的解决方案,请分享:)

    【讨论】:

    • 输入字符串 (.*?) 可以包含 |特点。如果现有 |在 flashplayer 标签之间,脚本不起作用,并将捕获的字符串附加到重写的字符串中。 powershell 可以将特殊字符解释为字符串与前面的“\”组合。有没有办法将输入字符串仅解释为字符串并忽略可选字符?接下来是输入和假输出字符串:[[http://a/b/docs/d/e | description ]][[http://a/b/docs/d/e | description|a/b/docs/d/e | description ]]现有的特殊字符处理得很好
    • 尝试更新的答案。我在-replace 命令中添加了一个转义方法,以确保它忽略特殊字符。如果它不起作用,您能否提供一个遵循该模式的不起作用的字符串? (flashplayer .....) sajdkaljdlsadkasd (/flashplayer)。请在提供代码时更新您的问题。在 cmets 中很难理解它们。 :)
    • 所以我的更新不起作用?这是新样本中的错字吗?您已将 (flashplay...) 替换为 &lt;flashplayer ...&gt;
    • 首先我的“大于”和“小于”符号不会被这篇文章接受。所以我把它改成了括号。更新后的样本至少是字符串的正确视图。 $search 中的搜索词大部分时间都会进行替换,但当反向链接代码行(请参阅更新)位于文本文件中时则不会。我调整后的搜索词是否正确?
    • &lt;&gt; 在您将其放入代码块时被接受,您应该始终这样做(这次有人为您修复了它)。在您的$search-pattern 中,您删除了我的前瞻/后视。这打破了文本替换。试试$search = '(?&lt;=&lt;flashplayer.*?&gt;file=/wiki/87sj38d/media)(.*?)(?=&lt;/flashplayer&gt;)'
    猜你喜欢
    • 1970-01-01
    • 2019-02-13
    • 2013-11-27
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    相关资源
    最近更新 更多