PowerShell: хранить все содержимое текстового файла в переменной

118

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

Ник
источник

Ответы:

122

Чтобы получить все содержимое файла:

$content = [IO.File]::ReadAllText(".\test.txt")

Количество строк:

([IO.File]::ReadAllLines(".\test.txt")).length

или

(gc .\test.ps1).length

Что-то вроде хакерства, чтобы включить завершающую пустую строку:

[io.file]::ReadAllText(".\desktop\git-python\test.ps1").split("`n").count
manojlds
источник
1
Спасибо! $content = [IO.File]::ReadAllText(".\test.txt")похоже, делает то же самое, что и $content = (gc ".\test.txt" | out-string). Поскольку второй из двух короче, я предпочитаю это. К сожалению, ни один из предложенных вами методов расчета общего количества строк не учитывает завершающие пустые строки. Есть другие идеи?
Ник
@Nick В .Net (и Windows) \r\nбудет засчитана любая строка с .
manojlds 02
Я экспериментировал и придумал то же, что и ваш обновленный ответ, но я бы не добился этого без вашей помощи, так что большое вам спасибо!
Ник
Есть ли способ прозрачно совместить это с Invoke-WebRequest?
Карим,
189

Кстати, в PowerShell 3.0 вы можете использовать Get-Contentкомандлет с новым переключателем Raw:

$text = Get-Content .\file.txt -Raw 
Шэй Леви
источник
3
Это должен быть принятый ответ. Кстати, я почти уверен, что Get-Content работала даже в более ранних версиях.
MatteoSp
10
@MatteoSp Get-Contentсделал, но не до версии 3.0 -Raw. Без этого он сохраняется как массив строк.
jpmc26
Это должен быть абсолютно принятый ответ. Не помогает то, что в документации сказано, что -Rawпараметр не реализован ни в чем родном.
Ричард Салай
Спасибо, это сейчас очень помогло.
DAhrens,
24

Powershell 2.0:

(см. подробное объяснение здесь)

$text = Get-Content $filePath | Out-String

У IO.File.ReadAllTextменя не получилось с относительным путем, он ищет файл %USERPROFILE%\$filePathвместо текущего каталога (по крайней мере, при запуске из Powershell ISE):

$text = [IO.File]::ReadAllText($filePath)

Powershell 3+:

$text = Get-Content $filePath -Raw
Капе
источник
Чтобы использовать пути родственников, сначала разрешите его, например:[IO.File]::ReadAllText((Resolve-Path $filePath))
mvanle
13

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

$content = ${C:file.txt}

Это обозначение может использоваться как L-значение или R-значение ; таким образом, вы можете легко записать в файл что-то вроде этого:

 ${D:\path\to\file.txt} = $content

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

${C:file.txt} = ${C:file.txt} | select -skip 1

Сначала я был очарован этим обозначением, потому что было очень трудно что-либо узнать о нем! Даже в спецификации PowerShell 2.0 он упоминается только один раз, показывая только одну строку, использующую его, но без каких-либо объяснений или деталей использования вообще. Впоследствии я нашел эту запись в блоге о переменных PowerShell, которая дает хорошее представление.

Последнее замечание по использованию этого: вы должны использовать обозначение диска, то есть, ${drive:filespec}как я делал во всех приведенных выше примерах. Без привода (например ${file.txt}) не работает. Никаких ограничений на спецификацию файлов на этом диске: она может быть абсолютной или относительной.

Майкл Соренс
источник
У меня никогда не получалось, чтобы это работало, если я не ставил обратную косую черту после имени диска.
Чарльз Андерсон
@CharlesAnderson: неясно, какой из трех примеров вы имеете в виду, или, возможно, все они ... тем не менее, я только что подтвердил, что все 3 работают с относительным путем (т.е. без обратной косой черты) в PowerShell V3. Кроме того, на момент своего ответа я использовал V2, поэтому, возможно, что-то еще вызывает проблему в вашей среде.
Майкл Соренс,
Я имел в виду такие примеры, как $ {C: file.txt}, которые я должен записать как $ {C: \ file.txt}. Да, я полагаю, это связано с моим окружением, но я понятия не имею, что именно.
Чарльз Андерсон
При использовании в качестве L-значения используется кодировка системы по умолчанию. Я попытался установить $ OutputEncoding безрезультатно. При использовании в качестве R-значения он создает массив string [].
robert4
Кажется, вы можете использовать только буквальный путь; внутри него нельзя использовать переменную или что-то вроде выражения Join-Path. Что раздражает, потому что при передаче через ConvertTo-Json есть огромная разница по сравнению с Get-Content (и результат $ {...} - это то, на что я надеялся. Я не уверен, что это то же самое как Get-Content | Out-String, хотя
Кэмерон Керр,
2

Get-Content собирает данные и построчно выгружает их в массив. Предполагая, что нет других особых требований, кроме перечисленных, вы можете просто сохранить свой контент в переменной?

$file = Get-Content c:\file\whatever.txt

Запуск просто $fileвернет полное содержимое. Затем вы можете просто $file.Count(поскольку в массивы уже встроен метод count) получить общее количество строк.

Надеюсь это поможет! Я не мастер сценариев, но мне это показалось проще, чем многое из вышеперечисленного.

Джерри Т.
источник