Поиск в цикле и замена двухкомпонентной строки над файлом с помощью PowerShell при сохранении одной из частей - PullRequest
0 голосов
/ 10 ноября 2018

Я новичок в PowerShell и не нашел вопрос переполнения стека или справочную документацию, которая поможет мне добиться успеха. Если уже существует вопрос или ссылка на документацию, которая отвечает на этот вопрос, который я пропустил, я был бы рад узнать.

В текстовом файле есть строка, подобная этой:

<span><span><span><span><span></span></span></span></span></span>

Количество <span> и </span> варьируется от файла к файлу. Например, в некоторых файлах это выглядит так:

<span></span>

И все же у других это так:

<span><span></span></span>

И так далее. Скорее всего, в строке никогда не будет больше 24 штук.

Я хочу исключить все подобные строки в текстовом файле, но сохранить </span> в следующих строках:

<span style="font-weight:bold;">text</span>

Там может быть много вариантов такого рода строки в текстовом файле; например, <span style="font-size: 10px; font-weight: 400;">text</span> или <span style="font-size: 10px; font-weight: 400;">text</span>, и я заранее не знаю, какие варианты будут включены в текстовый файл.

Это частично работает ...

$original_file = 'in.txt'
$destination_file = 'out.txt'

(Get-Content $original_file) | Foreach-Object {
    $_ -replace '<span>', '' `
       -replace '</span>', ''
} | Set-Content $destination_file

... но, очевидно, что-то вроде <span style="font-weight:bold;">text.

В приведенном выше сценарии PowerShell я могу использовать

    $_ -replace '<span></span>', '' `

Но, конечно, он только ловит <span></span> в середине строки, потому что, как написано сейчас, он не зацикливается.

Я знаю, что глупо делать что-то подобное

$original_file = 'in.txt'
$destination_file = 'out.txt'

(Get-Content $original_file) | Foreach-Object {
    $_ -replace '<span></span>', '' `
       -replace '<span></span>', '' `
       -replace '<span></span>', '' `
       -replace '<span></span>', '' `
       -replace '<span></span>', '' 
} | Set-Content $destination_file

Так как строка <span> сворачивается в себя при каждом запуске скрипта, создавая новый внутренний <span></span>, который затем может быть удален, лучшее решение, о котором я могу подумать, - это зацикливание скрипта над файлом до тех пор, пока признает, что все экземпляры <span></span> исчезли.

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

   foreach($i in 1..24){
    Write-Host $i

Но не удалось успешно включить его в сценарий.

Если это неверный подход, я был бы рад узнать.

Причина использования PowerShell в том, что моя команда предпочитает его для сценариев, включенных в конвейер выпуска Azure DevOps.

Спасибо за любые идеи или помощь.

Ответы [ 5 ]

0 голосов
/ 11 ноября 2018

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

$original_file = 'in.txt'
$destination_file = 'out.txt'

(Get-Content $original_file) -replace "(<span>)+(</span>)+" | 
 Set-Content $destination_file
0 голосов
/ 11 ноября 2018
$content = '<span></span><span><span><span style="font-weight:bold;">Foo</span></span></span>'
$regex = '<span\s+[^<]+</span>'
$null = $content -match $regex

$Matches[0]
0 голосов
/ 10 ноября 2018

Попробуйте следующее ... я добавил несколько комментариев, чтобы прояснить ситуацию.

# always use absolute paths if possible
$original_file = 'c:\tmp\in.txt'
$destination_file = 'c:\tmp\out.txt'

$patternToBeRemoved = '<span></span>'

# store the file contents in a variable
$fileContent = Get-Content -Path $original_file

# save the result of these operations in a new variable and iterate through each line
$newContent = foreach($string in $fileContent) {
    # while the pattern you don't want is found it will be removed
    while($string.Contains($patternToBeRemoved)) {
        $string = $string.Replace($patternToBeRemoved, '')
    }
    # when it's no longer found the new string is returned
    $string
}

# save the new content in the destination file
Set-Content -Path $destination_file -Value $newContent
0 голосов
/ 10 ноября 2018
$original_file = 'in.txt'
$destination_file = 'out.txt'

ForEach ($Line in (Get-Content $original_file)) {
    Do {
        $Line = $Line -replace '<span></span>',''
    } While ($Line -match '<span></span>')
    Set-Content -Path $destination_file -Value $Line 
}
0 голосов
/ 10 ноября 2018

Вы можете использовать регулярное выражение вместе с оператором -replace для удаления всех пар <span>optional content</span> из строки. Это означает, что все пары, где открывающий тег не указывает никаких атрибутов.

$content = '<span></span><span><span><span style="font-weight:bold;">Foo</span></span></span>'
$regex = '<span>(.*?)</span>'    
while ($content -match $regex)
{
    $content = $content -replace $regex,'$1'
}
Write-Output $content

Результат будет:

<span style="font-weight:bold;">Foo</span>

Цикл while заботится о ваших вложенных парах <span></span>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...