Заменяйте специальные символы в нескольких строках между двумя строками в PowerShell

Вопрос:

Предыстория: я изменил имена файлов.mp4 видео в нижнем регистре и заменил специальные символы, а также пробелы. Теперь мне нужно изменить связанные URL-адреса внутри.txt файлов аналогичным образом. Существует много текстовых файлов, которые содержат много этих 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)

Замена с помощью переименованного элемента должна быть:

  • ä = 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 $ показывает все строки правильно, но замена не работает должным образом.

Лучший ответ:

Вы можете попробовать что-то вроде этого. Для каждого текстового файла он заменяет специальные символы на каждой строке 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

}

UPDATE: Если текст содержит строки, то вы можете попробовать это глобальное многострочное соответствие регулярному выражению:

$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

Это немного сложнее, потому что AFAIK вы не можете изменить $1 (захваченная группа) при использовании -replace 'pattern', '$1' в текущей версии PowerShell. Если у кого-то есть лучшее решение, пожалуйста, поделитесь 🙂

Ответ №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” находятся “ä”, “ö”, “ü” или “”.

Оцените статью
TechArks.Ru
Добавить комментарий