Для открытия файлов и чтения его содержимого используется команда Powershell Get-Content. В этой статье рассмотрим работу команды с открытием файла, построчным чтением, поиском по содержимому строки на примерах.
Содержание[Скрыть]
Получение данных
Для открытия файла ‘C:text.txt’ можно использовать следующую команду:
1 |
Get-Content -Path 'C:WindowsSystem32driversetchosts' |
Если у вас множество файлов или вы не уверены в назывании, то вы можете использовать подстановку. Символы подстановок бывают следующих типов:
- ‘*’ — говорит об неизвестном количестве символов;
- [a,b] — говорит, что в этом месте может быть буква ‘a’ или ‘b’;
- ? — обозначает один неизвестный символ.
Каждый из символов выше можно применять вместе и неограниченное число раз, в любой части пути и имени.
В этом примере я открою сразу два файла: lmhosts и hosts:
1 |
Get-Content -Path 'C:WindowsSystem32driversetc*st*' |
Следующие примеры вернут аналогичный результат:
1 2 |
Get-Content -Path 'C:WindowsSystem32driversetc[l,h]*ost*' Get-Content -Path 'C:WindowsSystem32driversetc*h?st*' |
Для похожей фильтрации есть следующие параметры, которые так же позволяют использовать символы подстановок:
- Include — в этом параметре мы добавляем шаблон, по которому будем включать файл;
- Exclude — с помощью этого параметра исключает файлы;
- Filter — исключает результаты.
Для каждого из этих параметров есть обязательно условие — использовать знак ‘*’ в конце пути.
Так мы вернем все файлы с расширением ‘.txt’:
1 |
Get-Content -Path 'C:*' -Filter '*.txt' |
В отличие от Filter, в Include и Exclude мы можем использовать несколько значений. В этом примере мы откроем файлы формата ‘.txt’ и ‘.ini’:
1 |
Get-Content -Path 'C:*' -Include '*.txt','*.ini' |
Полное и построчное чтение с поиском
По умолчанию, если мы будем передавать результат команды через конвейер Powershell вывод будет построчный. Это может составить проблему, так как при дополнительных условиях у нас будет возвращаться одна строка, а не весь текст:
1 |
Get-Content -Path 'C:file*.txt' | Select-String -Pattern 'Line 8' |
Что бы текст передавался полностью, а не построчно — используйте параметр Raw:
1 |
Get-Content -Path 'C:file*.txt' -Raw | Select-String -Pattern 'Line 8' |
Если вам вдруг понадобится выводить по 2 или более строк за раз, можно указать их количество через ReadCount:
1 |
Get-Content -Path 'C:file*.txt' -ReadCount 2 | Select-String -Pattern 'Line 8' |
Разделение файла
Файл выводится построчно из-за делиметра (разделителя), который по умолчанию равен ‘n’ (идентификатор новой строки). Мы можем разделить файл иначе, например, использовав точку с запятой:
1 |
Get-Content -Path 'C:delimiter.txt' -Delimiter ';' |
То есть результат выше — это массив. В массивах Powershell мы можем получать содержимое по индексам. В следующем примере я просто уберу точку с запятой:
1 2 3 4 5 6 7 |
$content = Get-Content -Path 'C:delimiter.txt' -Delimiter ';' # Выведем первый элемент $content[0] # Уберем разделитель во всех адресах foreach ($c in $content){ $c -replace ';','' } |
Подсчет количества строк
Построчный вывод с командой Powershell позволяет посчитать количество строк во всем файле. Для подсчета используется команда Measure-Object:
1 |
Get-Content -Path 'C:file.txt' | measure |
Если нужна только цифра, а не объект, можно сделать так:
1 |
(Get-Content -Path 'C:file.txt' | measure).Count |
Кодировки
В параметре -Encoding можно указать следующие кодировки:
- ASCII
- BigEndianUnicode
- BigEndianUTF32
- Byte
- Default
- OEM
- Unicode
- UTF7
- UTF8
- UTF32
Чтения файла под другим пользователем
В этом командлете не предусмотрена возможность открытия файла под другим пользователем. При любых попытках вы будете получать ошибки:
- Access to the path is denied
- The FileSystem provider supports credentials only on the New-PSDrive cmdlet. Perform the operation again withoutspecifying credentials.
Для обхода этих ошибок, если у вас нет другого выхода, нужно использовать Invoke-Command (команда удаленного подключения). Для ее настройки могут потребоваться дополнительные настройки описанные в другой статье.
Сам процесс открытия файла под другим пользователем будет выглядеть так:
1 2 3 4 |
# Вводим свои учетные данные $creds = Get-Credential # Выполняем запрос под другим пользователем Invoke-Command -Computer localhost -Credential $creds -ScriptBlock {Get-Content -Path 'C:FolderFile2.txt'} |
Непрерывное чтение
С помощью параметра Wait вы можете читать файл, который в этот момент обновляется системой или другим пользователем:
1 |
Get-Content -Path 'C:file1.txt' -Wait |
Ограничение вывода строк
Можно ограничить вывод содержимого файла указав количество нужных строк в начале или конце:
- Head — выведет указанное количество строк с начала;
- Tail — выведет указанное количество строк с конца.
Так будут выведены только первые 5 строк:
1 |
Get-Content -Path 'C:file1.txt' -Head |
Поиск файлов по содержимому
Get-Content не позволяет искать и открывать фалы находящиеся внутри других каталогов. Такой поиск называется рекурсивным и он доступен в Get-ChildItem.
В следующем примере мы вернем файлы из всех каталогов и подкаталогов:
1 |
Get-ChildItem -Path 'C:Windows' -Recurse -File |
File — возвращает только файлы. Каталоги нам не нужны.
С Get-ChildItem вы так же можете использовать Include,Exclude и Filter, которые были рассмотрены раннее. Использовать эти ключи лучше всего в первой команде т.к. это будет работать быстрее.
Через конвейер мы сможем открыть каждый файл, а с Select-Sting проверить есть ли в нем нужный текст. Так мы найдем файл с Powershell, который содержит строку ‘127.0.0.1’ в папке Windows:
1 2 3 |
Get-ChildItem -Path 'C:WindowsSystem32driversetc' -Recurse -File | Get-Content -Raw | Select-String '127.0.0.1' |
Если убрать параметр Raw, то у нас выведется только та строка, которую мы искали:
Изменение файла с последующей записью
Вы так же можете изменить содержимое файла и перезаписать этот файл. Представим, что вам нужно заменить адрес ‘127.0.0.1’ в строке — это можно сделать так:
1 |
'My address: 127.0.0.1/24' -replace '127.0.0.1','192.168.3.2' |
Или с помощью регулярного выражения (не точный шаблон):
1 |
'My address: 127.0.0.1/24' -replace 'd{1,3}.d{1,3}.d{1,3}.d{1,3}','192.168.3.2' |
Для записи в файл у нас есть два варианта. Первый — это использовать перенаправление в виде знака ‘>’, который перезапишет все содержимое файла или создаст новый файл:
1 2 |
$file_content = Get-Content -Path 'C:file1.txt' $file_content -replace '127.0.0.1','192.168.3.2' > file1.txt |
Второй вариант — использовать команду Set-Content:
1 2 |
$file_content = Get-Content -Path 'C:file1.txt' $file_content -replace '127.0.0.1','192.168.3.2' | Set-Content -Path 'C:file1.txt' |
Подсчет четных чисел в файле
У меня есть файл ‘file.txt’ со следующим содержанием:
1 2 3 |
some text 123 some text 6 some text 9 some text 312345 123.2 |
Шаблон регулярного выражения ‘d*.?d*’ говорит, что мы ищем число, после которого может быть точка, после которого могут быть еще числа. Таким образом мы захватим целые и числа с плавающей точкой.
Для выделения таких чисел из строк нужно использовать Select-String:
1 2 |
$file = Get-Content -Path 'file.txt' $result = Select-String -InputObject $file -Pattern 'd*.?d*' -AllMatches | Foreach {$_.matches} |
Нам нужно отформатировать вывод убрав пустые строки и получить значения свойства Value:
1 |
$result | where Value -ne '' | select Value |
Мы можем вернуть остаток от деления использовав %. Если число делится на 2 с остатком 0, то оно будет четным:
1 2 3 4 5 6 7 8 9 10 11 12 |
# Открываем файл $opened_file = Get-Content -Path 'file.txt' # Поиск чисел $result = Select-String -InputObject $opened_file -Pattern 'd*.?d*' -AllMatches | Foreach {$_.matches} # Исключение пустых строк в выводе $result = ($result | where Value -ne '').Value foreach ($num in $result){ # Результат деления $n = $num%2 if ($n -eq 0){Write-Output "Число четное: $num"} else {Write-Output "Число не четное: $num"} } |
Ваш комментарий будет первым