Главная > Powershell > Чтение нескольких частей файла через Powershell

Чтение нескольких частей файла через Powershell

Сегодня мне в комментарии к статье “Чтение части файла через Powershell” задали такой вопрос:

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

Вопрос мне показался довольно интересным, и в результате решения родился этот пост.

Итак, напомню для того, чтобы прочесть кусок файла для начала этот файл нужно считать как одну строку, после чего “выцарапать” из него нужную нам часть, находящуюся между какими-нибудь разделителями:

# Читаем файл как одну строку
$file = [System.IO.File]::ReadAllText("file.txt")

# Индекс начала
$start = $file.IndexOf("начало")
# Индекс конца
$end = $file.IndexOf("конец")

# Читаем выделенный текст
$file.Substring($start, $end-$start)

Этот метод прекрасно работает, если нужно найти один кусок текста. Если таких кусков несколько, очевидно, что нужно их считывать в цикле. Загвоздка в том, какой делать цикл? Раз у нас есть индексы начала и конца, логично было бы воспользоваться ими для задания условий. Так, было решено читать файл до тех пор, пока встречается начальный и конечный разделитель (на случай если начальному не будет найдено пары).

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

  • файл обрезается начиная с первого символа после индекса конечного разделителя ($end+1) и до конца – т.е. нашли нужный кусок, выбрали его, и всё, что было до него выбросили;
  • в оставшейся части файла заново ищутся начальный и конечный индексы разделителей;
  • “выцарапывается” найденный текст.

Всё это повторяется до тех пор, пока в тексте присутствуют разделители (их индексы больше нуля).

Это замечательно работает с единственной оговоркой – когда разделители больше не находятся один раз вылазит ошибка "Исключение при вызове "Substring" с "2" аргументами: "StartIndex cannot be less than zero." Поэтому был ещё добавлен блок try-catch для её отлавливания.

В виде кода это выглядит так:

while ($start -gt 0 -and $end -gt 0)
{
    try
    {
        # "Обрезаем файл"
        $file = $file.Substring($end+1)

        # И продолжаем читать
        $start = $file.IndexOf("начало")
        $end = $file.IndexOf("конец")
        $file.Substring($start, $end-$start)
    }
    catch
    {
        Write-Warning $_.Exception.Message
        Write-Host "`nТ.е. больше такие разделители не встречаются`n"
    }
}

Если не нужно блок catch можно оставить пустым.

Писалось на скорую руку, может быть не самый элегантный способ, но работает 🙂

Реклама
Рубрики:Powershell Метки: ,
  1. frankk
    10/09/2013 в 16:40

    А можешь подсказать как получить урезанную часть текста. например получить первую часть текста, состоящую из 2000 символов? Или придется считать текст весь текст и плясать отсюда? Есть мысли?

    • 11/09/2013 в 12:47

      Как вариант — считать весь файл, и выбрать нужное количество символов:

      $File = [system.IO.File]::ReadAllText($FilePath)
      $File.Substring(0,2000)

  2. frankk
    17/09/2013 в 12:23

    Спасибо. попробую!!! Спасибо за твои статьи, очень помогают!

  1. No trackbacks yet.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: