Итак, подведём итоги этого года 🙂 В области регулярных выражений разумеется 🙂 Мы успели познакомится с основами, отрицательными группами и якорями, квантификаторами, группами захвата, операторами –replace и –split, а так же с концепцией “жадности”. Пришло время познакомится с целым командлетом PowerShell, который использует регулярные выражения. Таким командлетом является Select-String
. Он используется для поиска строк совпадающих с регулярным выражением. Строки для отбора можно передать из массива строк, например:
PS C:\> $lines = Get-Content C:\Windows\setupact.log
PS C:\> $lines | Select-String "error"
dispci.dll: DispCIOpenDxgKrnlAndDisableNewReferences: D3DKMTOpenAdapterFromDeviceName failed with error 0xc000007a.
[10/24/2009 20:47.16.192] WudfCoInstaller: Final status: error(0) The operation completed successfully.
[10/26/2009 14:45.08.912] WudfCoInstaller: Final status: error(0) The operation completed successfully.
[10/27/2009 18:24.13.032] WudfCoInstaller: Final status: error(0) The operation completed successfully.
[10/27/2009 18:24.14.421] WudfCoInstaller: Final status: error(0) The operation completed successfully.
[11/02/2009 11:32.22.880] WudfCoInstaller: Final status: error(0) The operation completed successfully.
[11/13/2009 15:16.16.837] WudfCoInstaller: Final status: error(0) The operation completed successfully.
Еще можно указывать файлы для проверки содержащихся в них строк, просто указав их путь, или маску (с помощью обычных подстановочных знаков). Так в следующем примере я делаю поиск строки error: во всех файлах *.log
в папке c:\Windows:
PS C:\> Select-String "error:" C:\Windows\*.log
TSSysprep.log:7:sysprep.cpp(314)ERROR: ResetTSPublicPrivateKeys() FAILED: 2
WindowsUpdate.log:2663:2009-10-31 15:11:26:983 896 13fc PT WARNING: PTError: 0x80072ee2
WindowsUpdate.log:3926:2009-11-01 19:09:14:748 896 548 PT WARNING: PTError: 0x8024402c
WindowsUpdate.log:3930:2009-11-01 19:09:14:749 896 548 PT WARNING: PTError: 0x8024402c
WindowsUpdate.log:3941:2009-11-01 19:09:28:778 896 548 PT WARNING: PTError: 0x8024402c
WindowsUpdate.log:3945:2009-11-01 19:09:28:778 896 548 PT WARNING: PTError: 0x8024402c
WindowsUpdate.log:3956:2009-11-01 19:09:42:808 896 548 PT WARNING: PTError: 0x8024402c
WindowsUpdate.log:3960:2009-11-01 19:09:42:808 896 548 PT WARNING: PTError: 0x8024402c
Select-String
отличается от конструкции where {$_ -match "error:"}
тем что выводит не просто совпадения строк, а полноценные объекты содержащие дополнительную информацию. В данном случае были выведены не только совпавшие строки, но и файлы в которых они были найдены (TSSysprep.log и WindowsUpdate.log), и номера строк. Полный список доступных свойств можно посмотреть следующей командой:
PS C:\> Select-String "error:" C:\Windows\*.log |
>> Get-Member -MemberType property
TypeName: Microsoft.PowerShell.Commands.MatchInfo
Name MemberType Definition
---- ---------- ----------
Context Property Microsoft.PowerShell.Commands.MatchInfoContext Context {get;set;}
Filename Property System.String Filename {get;}
IgnoreCase Property System.Boolean IgnoreCase {get;set;}
Line Property System.String Line {get;set;}
LineNumber Property System.Int32 LineNumber {get;set;}
Matches Property System.Text.RegularExpressions.Match[] Matches {get;set;}
Path Property System.String Path {get;set;}
Pattern Property System.String Pattern {get;set;}
Давайте например выведем только имена файлов и номера совпавших строк:
PS C:\> Select-String "error:" C:\Windows\*.log |
>> Format-Table Path, LineNumber -AutoSize
Path LineNumber
---- ----------
C:\Windows\TSSysprep.log 7
C:\Windows\WindowsUpdate.log 2663
C:\Windows\WindowsUpdate.log 3926
C:\Windows\WindowsUpdate.log 3930
C:\Windows\WindowsUpdate.log 3941
C:\Windows\WindowsUpdate.log 3945
C:\Windows\WindowsUpdate.log 3956
C:\Windows\WindowsUpdate.log 3960
Если весь этот "объектный мусор" вам не нужен, вы можете получить только строки, следующей командой:
PS C:\> Select-String "error:" C:\Windows\*.log |
>> Select-Object -ExpandProperty line
sysprep.cpp(314)ERROR: ResetTSPublicPrivateKeys() FAILED: 2
2009-10-31 15:11:26:983 896 13fc PT WARNING: PTError: 0x80072ee2
2009-11-01 19:09:14:748 896 548 PT WARNING: PTError: 0x8024402c
2009-11-01 19:09:14:749 896 548 PT WARNING: PTError: 0x8024402c
2009-11-01 19:09:28:778 896 548 PT WARNING: PTError: 0x8024402c
2009-11-01 19:09:28:778 896 548 PT WARNING: PTError: 0x8024402c
2009-11-01 19:09:42:808 896 548 PT WARNING: PTError: 0x8024402c
2009-11-01 19:09:42:808 896 548 PT WARNING: PTError: 0x8024402c
У Select-String
есть и несколько дополнительных возможностей. Так если вам не интересно знать какие строки совпали, а лишь необходимо выяснить были ли совпадения вообще, воспользуйтесь ключем -Quiet:
PS C:\> netsh advfirewall firewall show rule "Remote Desktop (TCP-In)" |
>> select-string "Enabled:\s+Yes" -Quiet
True
Эта команда проверяет, содержится ли в выводе netsh
строка совпадающая с Enabled:\s+Yes
и если содержится, то выводит значение $True
. Разумеется тут тоже можно указывать напрямую имя файла или несколько с помощью подстановочных символов, тогда True
будет выдано в случае если хотя бы один из файлов содержит указанную строку.
Параметр -List
говорит Select-String
что нужно найти лишь по одному совпадению на каждый файл. Это может быть полезно если вам надо найти все файлы содержащие определенную строку:
PS C:\> Select-String "error:" C:\Windows\*.log -List |
>> select -ExpandProperty path
C:\Windows\TSSysprep.log
C:\Windows\WindowsUpdate.log
В PowerShell 2.0 у Select-String
появился еще один очень полезный ключ — -Context
. Он позволяет вывести не только совпавшую строку, но еще и указанное количество строк до неё и после неё. В следующем примере выводится 3 строки предшествующих совпадению и одна после него:
PS C:\> Select-String "error:" C:\Windows\TSSysprep.log -Context 3,1
Windows\TSSysprep.log:4:*******Version:Major=6, Minor=1, Build=7600, PlatForm=2, CSDVer=, Free
Windows\TSSysprep.log:5:
Windows\TSSysprep.log:6:sysprep.cpp(309)Entering RCMSysPrepRestore
> Windows\TSSysprep.log:7:sysprep.cpp(314)ERROR: ResetTSPublicPrivateKeys() FAILED: 2
Windows\TSSysprep.log:8:sysprep.cpp(316)Leaving RCMSysPrepRestore
Непосредственно совпавшая строка помечается с помощью символа >
в начале строки. Если указать в качестве аргумента не массив из двух элементов, а просто число, то будет выведено указанное количество строк с обоих сторон от совпадения:
PS C:\> netsh advfirewall firewall show rule "Remote Desktop (TCP-In)" |
>> select-string "Enabled:" -Context 2
Rule Name: Remote Desktop (TCP-In)
----------------------------------------------------------------------
> Enabled: Yes
Direction: In
Profiles: Domain,Private,Public
В Select-String тоже можно использовать группы захвата, хотя получить их содержимое несколько сложнее. Дело в том что тут не используется специальная переменная $Matches
, а вместо неё результаты совпадаения, в виде объекта System.Text.RegularExpressions.Match
помещаются в свойство Matches
результирующего объекта. Подробнее устройство этого объекта мы рассмотрим позднее, когда будем изучать класс [Regex]
, а пока я просто покажу как же можно получить например значение первой группы захвата:
PS C:\> Select-String "error: (\S+)" C:\Windows\*.log |
>> Format-table path,linenumber,{$_.Matches[0].groups[1].value}
Path LineNumber $_.Matches[0].groups[1].value
---- ---------- -----------------------------
C:\Windows\TSSysprep.log 7 ResetTSPublicPrivateKeys()
C:\Windows\WindowsUpdate.log 2663 0x80072ee2
C:\Windows\WindowsUpdate.log 3926 0x8024402c
C:\Windows\WindowsUpdate.log 3930 0x8024402c
C:\Windows\WindowsUpdate.log 3941 0x8024402c
C:\Windows\WindowsUpdate.log 3945 0x8024402c
C:\Windows\WindowsUpdate.log 3956 0x8024402c
C:\Windows\WindowsUpdate.log 3960 0x8024402c
Другие полезные параметры командлета на которые стоит обратить внимание, это -CaseSensetive
, -Encoding
и -NotMatch
. Их названия говорят сами за себя, поэтому не буду показывать примеры для каждого.
Продолжение следует, но уже в следующем году 🙂
Пользуясь случаем хочу пожелать всем читателям моего блога успехов в следующем году. Чтобы скрипты экономили вам еще больше времени принося больше дохода, и доставляя всё больше удовольствия от работы. Ну и просто счастья и здоровья конечно 🙂 До встречи в новом году!