Как скопировать только предложения между двумя заголовками - PullRequest
0 голосов
/ 23 октября 2019

У меня есть текстовый файл, в котором много заголовков и несколько предложений под ним. Я хотел найти заголовок, и если заголовок доступен, я хочу скопировать предложения ниже заголовка до следующего заголовка.

Возможно ли это в PowerShell, помогите, пожалуйста, я попытался

$linenumber= Get-Content "C:\Users\KSYEDSU\Documents\temp\4491309.txt" | select-string $search
Select-String $string $dataRead -Context 1, $linenumber| % { $_.Context.PostContext } |  out-file "C:\Users\KSYEDSU\Documents\temp\Results.txt"

Но он выдает ошибку, сообщая, что ожидает интергер

$linenumber= Get-Content "C:\Users\KSYEDSU\Documents\temp\4491309.txt" | select-string $search
Select-String $string $dataRead -Context 1, $linenumber| % { $_.Context.PostContext } |  out-file "C:\Users\KSYEDSU\Documents\temp\Results.txt"

ex:

Heading A
1234
34545
13213
Heading B

Так что я буду искать заголовок A, и если он будет доступен, тогда начнем копирование from 1234... till 13213.

Ответы [ 3 ]

0 голосов
/ 23 октября 2019

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

$headingStart = 'Heading A'
$headingEnd   = 'Heading B'

# get the file content in one string, including all newline characters
$content = Get-Content "C:\Users\KSYEDSU\Documents\temp\4491309.txt" -Raw

# since the real headings may contain characters that have special meaning in regex, we escape them
$regex   = '(?s)^{0}\s+(.*)\s{1}' -f [regex]::Escape($headingStart), [regex]::Escape($headingEnd)
if ($content -match $regex) {
    $matches[1] | Out-File -FilePath "C:\Users\KSYEDSU\Documents\temp\Results.txt"
} 
else {
    Write-Host "No text found between $headingStart and $headingEnd"
}

Используя ваш пример, полученный файл будет содержать:

1234
34545
13213
0 голосов
/ 23 октября 2019

Вы можете использовать оператор switch в сочетании с флагами -Regex и -File.

$insideHeaders = $false

. {switch -Regex -File "C:\Users\KSYEDSU\Documents\temp\4491309.txt" {
    'Heading A' { $insideHeaders = $true }
    'Heading B' { return }
    default {
        if ($insideHeaders) { $_ }
    }
}} | Out-File "C:\Users\KSYEDSU\Documents\temp\Results.txt"

Объяснение:

Каждое значение в одинарных кавычкахстрока регулярного выражения. Вам придется использовать обратную косую черту (\), экранируя любые специальные символы регулярных выражений, что можно сделать автоматически, используя [regex]::Escape(string).

Когда достигается нижний заголовок (в данном случае Heading B), return оператор завершит работу оператора switch.

Все строки, не соответствующие одному из заголовков, вызовут условие по умолчанию. Условие по умолчанию выводит строку только в том случае, если был найден первый заголовок.

0 голосов
/ 23 октября 2019

Select-String найдет строку внутри вашего текста, но не вернет позицию как int. Вы можете зациклить свой файл и вручную искать заголовок и собирать данные между ними.

#Get file content as string array
[System.String[]]$FileContent = Get-Content -Path 'C:\Users\KSYEDSU\Documents\temp\4491309.txt'

#For each line in the file
for ($i = 0; $i -lt $FileContent.Count; $i ++)
{
    #If the line equals your start header
    if ($FileContent[$i] -eq 'Heading A')
    {
        $i ++ #Get the next line

        #Return line until end header appears
        while ($FileContent[$i] -ne 'Heading B')
        {
            $FileContent[$i] #Return line
            $i ++ #Get next line
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...