ЛАБОРАТОРНЫЕ РАБОТЫ ОС (Для допуска необходимо сделать 1 или 6 л. Практикум по дисциплине Операционные системы (ОС). Цели лабораторных занятий это формирование у будущих бакалавров направлений подготовки 09. 03. 01
![]()
|
Исходный набор строк: wake make machine cake maze Регулярное выражение: ma.e Результат: make maze \w Замещает любые символы, которые относятся к буквам, цифрам и знаку подчеркивания. Пример: Исходный набор строк: abc а$с 76 Метасим вол Описание метасимвола a1c а с Регулярное выражение: a\wc Результат: abc a1c \W Замещает все символы, кроме букв, цифр и знака подчеркивания (то есть является обратным метасимволу \w). Пример: Исходный набор строк: abc а$с a1c а с Регулярное выражение: a\Wc Результат: а$с а с \d Замещает все цифры. Продемонстрируем его действие на том же примере: Исходный набор строк: abc а$с a1c а с Регулярное выражение: a\dc Результат: alc \D Замещает все символы, кроме цифр, например: Исходный набор строк: abc а$с alc а с Регулярное выражение: a\Dc Результат: abc а$с а с 77 1.10.4 Количественные модификаторы (квантификаторы) Обычно регулярные выражения гораздо сложнее, чем приведенные выше, и записывать их по одному символу было бы тяжеловато. Например, нужно отобрать строки, состоящие из четырех символов, каждый из которых может быть буквой от A до F или цифрой? Регулярное выражение могло бы выглядеть примерно так: PS C:\> "af12","1FE0","1fz1","B009","C1212" -match "^[a-f\d][a-f\d][a-f\d][a- f\d]$" af12 1FE0 B009 Не слишком то лаконично, не правда ли? К счастью всю эту конструкцию можно значительно сократить. Для этого в регулярных выражениях существует специальная конструкция – "количественные модификаторы" (квантификаторы). Эти модификаторы приписываются к любой группе справа, и определяют количество вхождений этой группы. Например, количественный модификатор {4} означает 4 вхождения. Посмотрим на приведенном выше примере: PS C:\> "af12","1FE0","1fz1","B009","C1212" -match "^[a-f\d]{4}$" af12 1FE0 B009 Данное регулярное выражение полностью эквивалентно предыдущему – "4 раза по [a-f\d]". Но этот количественный модификатор не обязательно жестко оговаривает количество повторений. Например,можно задать количество как "от 4 до 6". Делается это указанием внутри фигурных скобок двух чисел через запятую – минимума и максимума: PS C:\> "af12","1FE0","1fA999","B009","C1212","A00062","FF00FF9" - match "^[a-f\d]{4,6}$" af12 1FE0 1fA999 B009 C1212 A00062 Если максимальное количество вхождений безразлично, например, нужно указать "3 вхождения или больше", то максимум можно просто опустить (оставив запятую на месте), например "строка состоящая из 3х или более цифр": PS C:\> "1","12","123","1234","12345" -match "^\d{3,}$" 123 1234 78 12345 Минимальное значение опустить нельзя, но можно просто указать единицу: PS C:\> "1","12","123","1234","12345" -match "^\d{1,3}$" 1 12 123 Как и в случае с символьными группами, для особенно популярных значений количественных модификаторов, есть короткие псевдонимы: + (плюс), эквивалентен {1,} то есть, "одно или больше вхождений" * (звездочка), то же самое что и {0,} или на русском языке – "любое количество вхождений, в том числе и 0" ? (вопросительный знак), равен {0,1} – "либо одно вхождение, либо полное отсутствие вхождений". В регулярных выражениях, количественные модификаторы сами по себе использоваться не могут. Для них обязателен символ или символьная группа, которые и будут определять их смысл. Вот несколько примеров: .+ Один или более любых символов. Аналог ?* в простых подстановках (как в cmd.exe). Следующее выражение выбирает процессы, у которых имя "начинается с буквы S, затем следует 1 или более любых символов, затем снова буква S и сразу после неё конец строки". Иначе говоря "имена которые начинаются и заканчиваются на S": PS C:\> Get-Process | where {$_.name -match "^s.+s$"} (рис.10) Рис.10-"имена которые начинаются и заканчиваются на S" \S* Любое количество символов не являющихся пробелами. Подобное выражение может совпасть и с ""(с пустой строкой), ведь под любым количеством подразумевается и ноль, то есть 0 вхождений – тоже результат. PS C:\> "abc", "cab", "a c","ac","abdec" -match "a\S*c" abc ac abdec Заметьте, строка "ac" тоже совпала, хотя между буквами A и C вообще не было символов. Если заменить * на + то будет иначе: 79 PS C:\> "abc", "cab", "a c","ac","abdec" -match "a\S+c" abc abdec бобры? (Это не вопрос, а регулярное выражение). Последовательность "бобр", после которой может идти символ "ы", а может и отсутствовать: PS C:\> "бобр","бобры","бобрята" -match "^бобры?$" Бобр бобры 1.10.5 Группы захвата и переменная $matches Теперь, когда мы можем с помощью регулярных выражений описывать и проверять строки по достаточно сложным правилам, пора познакомится с другой не менее важной возможностью регулярных выражений – "группами захвата" (capture groups). Как следует из названия, группы можно использовать для группировки. К группам захвата, как и к символам и символьным группам, можно применять количественные модификаторы. Например, следующее выражение означает "Первая буква в строке – S, затем одна или больше групп, состоящих из “знака - (минус) и любого количества цифр за ним” до конца строки": PS C:\> "S-1-5-21-1964843605-2840444903-4043112481" -match "^S(-\d+)+$" True Или: PS C:\> "Ноут","Ноутбук","Лептоп" -match "Ноут(бук)?" Ноут Ноутбук Эти примеры показывают, как можно использовать группы захвата для группировки, но это вовсе не главное их качество. Гораздо важнее то, что часть строки, подпавшая под подвыражение, находящееся внутри такой группы, помещается в специальную переменную – $matches. $Matches - это массив, и в нем может находится содержимое нескольких групп. Причем под индексом 0 туда помещается вся совпавшая строка, начиная с единицы идет содержимое групп захвата. Рассмотрим пример: PS C:\> "At 17:04 Firewall service was stopped." -match "(\d\d:\d\d) (\S+)" True PS C:\> $matches Name Value ---- ----- 2 Firewall 1 17:04 0 17:04 Firewall Под индексом 0 находится вся часть строки, подпавшая под регулярное выражение, под 1 находится содержимое первых скобок, и под 2 соответственно содержимое вторых скобок. К содержимому $matches 80 можно обращаться как к элементам любого другого массива в PowerShell: PS C:\> $matches[1] 17:04 PS C:\> $matches[2] Firewall Если в строке присутствует много групп захвата, то бывает полезно дать им имена, это сильно облегчает дальнейшую работу с полученными данными: PS C:\> "At 17:04 Firewall service was stopped." -match "(?<Время>\d\d:\d\d) (?<Служба>\S+)" True PS C:\> $matches Name Value ---- ----- Время 17:04 Служба Firewall 0 17:04 Firewall PS C:\> $matches.Время 17:04 PS C:\> $matches["Служба"] Firewall Регулярное выражение конечно усложнилось, но зато работать с результатами гораздо приятнее. Синтаксис именования следующий: (?<Название Группы>подвыражение) Не перепутайте порядок, сначала следует знак вопроса. Количественные модификаторы, в том числе ? могут применяться только после группы, и следовательно в начале подвыражения – бессмысленны. Поэтому в группах знак вопроса, следующий сразу за открывающей скобкой, означает особый тип группы, в нашем примере – именованную. Другой тип группы, который часто используется – незахватывающая группа. Она может пригодиться в тех случаях, когда не нужно захватывать содержимое группы, а надо применить её только для группировки. Например, в вышеприведённом примере с SID, такая группа была бы более уместна: PS C:\> "S-1-5-21-1964843605-2840444903-4043112481" -match "^S(?:- \d+)+$" True PS C:\> $matches 81 Name Value ---- ----- 0 S-1-5-21-1964843605-2840444903-4043112481 Синтаксис такой группы: (?:подвыражение). Группы можно и вкладывать одну в другую: PS C:\> "MAC address is '00-19-D2-73-77-6F'." -match "is '([a-f\d]{2}(?:-[a- f\d]{2}){5})'" True PS C:\> $matches Name Value ---- ----- 1 00-19-D2-73-77-6F 0 is '00-19-D2-73-77-6F' 1.11 Управляющие инструкции 1.11.1 Инструкция If …ElseIf … Else В общем случае синтаксис инструкции If имеет вид If (условие1) {блок_кода1} [ElseIf (условие2)] {блок_кода2}] [Else {блок_кода3}] При выполнении инструкции If проверяется истинность условного выражения условие1. Если условие1 имеет значение $True, то выполняется блок_кода1, после чего выполнение инструкции if завершается. Если условие1 имеет значение $False, проверяется истинность условного выражения условие2. Если условие2 имеет значение $True, то выполняется блок_кода2 и выполнение инструкции if завершается. Если и условие1, и условие2 имеют значение $False, то выполняется блок_кода3 и выполнение инструкции if завершается. Пример 2. использования инструкции if в интерактивном режиме работы. Сначала переменной $a присвоим значение 10: PS C:\> $a=10 Затем сравним значение переменной с числом 15: PS C:\> If ($a –eq 15) { >> ‘Значение $a равно 15’ >> } >> Else {‘ Значение $a не равно 15‘} 82 >> Значение $a не равно 15 Из приведенного примера видно также, что в оболочке PS в интерактивном режиме можно выполнять инструкции, состоящие из нескольких строк, что полезно при отладке сценариев. 1.11.2 Циклы While и Do … While Самый простой из циклов PS – цикл While, в котором команды выполняются до тех пор, пока проверяемое условие имеет значение $True. Инструкция While имеет следующий синтаксис: While (условие) {блок_команд} Цикл Do … While похож на цикл While, однако условие в нем проверяется не до блока команд, а после: Do {блок_команд} While (условие). Например: PS C:\> $val=0 PS C:\>Do {$val++; $val} While ($val –ne 3) 1 2 3 1.11.3 Цикл For Обычно цикл For применяется для прохождения по массиву и выполнения определенных действий с каждым из его элементов. Синтаксис инструкции For: For (инициация; условие; повторение) {блок_команд}. Пример PS C:\> For ($i=0; $i –lt 3; $i++) {$i } 0 1 2 1.11.4 Цикл ForEach Инструкция ForEach позволяет последовательно перебирать элементы коллекций. Самый простой тип коллекции – массив. Особенность цикла ForEach состоит в том, что его синтаксис и выполнение зависят от того, где расположена инструкция ForEach: вне конвейера команд или внутри конвейера. Инструкция ForEach вне конвейера команд: В этом случае синтаксис цикла ForEach имеет вид: ForEach ($элемент in $коллекция) {блок_команд} При выполнении цикла ForEach автоматически создается переменная $элемент. Перед каждой итерацией в цикле этой переменной присваивается эначение очередного элемента в коллекции. В разделе блок_команд содержатся команды, выполняемые на каждом элементе коллекции. Приведенный ниже цикл ForEach отображает значения 83 элементов массива $lettArr: PS C:\> $lettArr = “a”, “b”,”c” PS C:\> ForEach ($lett in $lettArr) {Write-Host $lett} a b c Инструкция ForEach может также использоваться совместно с командлетами, возвращающими коллекции элементов. Например: PS C:\> $ln = 0; ForEach ($f in Dir *.txt) {$ln +=$f.length} В примере создается и обнуляется переменная $ln, затем в цикле ForEach с помощью командлета dir формируется коллекция файлов с расширением txt, находящихся в текущем каталоге. Инструкция ForEach перебирает все элементы этой коллекции, на каждом шаге к текущему файлу выполняется обращение с помощью переменной $f. В блоке команд цикла ForEach к текущему значению переменной $ln добавляется значение свойства Length (размер файла) переменной $f. В результате выполнения цикла в переменной $ln будет получен суммарный размер файлов в текущем каталоге, которые имеют расширение txt. Инструкция ForEach внутри конвейера команд: Если инструкция ForEach появляется внутри конвейера команд, то PS использует псевдоним ForEach, соответствующий командлету ForEach- Object. В этом случае фактически выполняется командлет ForEach-Object и не требуется часть инструкции ($элемент in $коллекция), так как элементы коллекции блоку команд предоставляет предыдущая команда конвейера. Синтаксис инструкции ForEach внутри конвейера команд имеет вид: команда | ForEach {блок_команд} Рассмотренный выше пример подсчета суммарного размера файлов из текущего каталога для данного варианта инструкции ForEach примет следующий вид: PS C:\> $ln = 0; dir *.txt | ForEach { $ln +=$_.Length} В приведенном примере специальная переменная $_ используется для обращения к текущему объекту конвейера и извлечения его свойств. 1.12 Управление выводом команд в PowerShell Рассмотрим, каким образом система формирует строки текста, которые выводятся на экран в результате выполнения той или иной команды (напомним, что командлеты PowerShell возвращают .NET- объекты, которые, как правило, не знают, каким образом отображать себя на экране). В PowerShell имеется база данных (набор XML-файлов), содержащая 84 модули форматирования по умолчанию для различных типов .NET- объектов. Эти модули определяют, какие свойства объекта отображаются при выводе и в каком формате: списка или таблицы. Когда объект достигает конца конвейера, PowerShell определяет его тип и ищет его в списке объектов, для которых определено правило форматирования. Если данный тип в списке обнаружен, то к объекту применяется соответствующий модуль форматирования; если нет, то PowerShell просто отображает свойства этого .NET-объекта. Также в PowerShell можно явно задавать правила форматирования данных, выводимых командлетами, и подобно командному интерпретатору Cmd.exe перенаправлять эти данные в файл, на принтер или в пустое устройство. 1.12.1 Форматирование выводимой информации В традиционных оболочках команды и утилиты сами форматируют выводимые данные. Некоторые команды (например, dir в интерпретаторе Cmd.exe) позволяют настраивать формат вывода с помощью специальных параметров. В оболочке PowerShell вывод форматируют только четыре специальных командлета Format (табл. 4). Это упрощает изучение, так как не нужно запоминать средства и параметры форматирования для других команд (остальные командлеты вывод не форматируют). Таблица 4. Командлеты PowerShell для форматирования вывода Командлет Описание Format- Table Форматирует вывод команды в виде таблицы, столбцы которой содержат свойства объекта (также могут быть добавлены вычисляемые столбцы). Поддерживается возможность группировки выводимых данных Format- List Вывод форматируется как список свойств, в котором каждое свойство отображается на новой строке. Поддерживается возможность группировки выводимых данных Format- Custom Для форматирования вывода используется пользовательское представление (view) Format- Wide Форматирует объекты в виде широкой таблицы, в которой отображается только одно свойство каждого объекта Как уже отмечалось, если ни один из командлетов Format явно не указан, то используется модуль форматирования по умолчанию, который определяется по типу отображаемых данных. Например, при выполнении командлета Get-Service данные по умолчанию выводятся как таблица с 85 тремя столбцами (Status, Name и DisplayName): (рис.11) PS C:\> Get-Service Рис.11- таблица с тремя столбцами (Status, Name и DisplayName) Для изменения формата выводимых данных нужно направить их по конвейеру соответствующему командлету Format . Например, следующая команда выведет список служб с помощью командлета Format-List : PS C:\> Get-Service | Format-List (рис.12.) Рис.12- Список служб с помощью командлета Format-List 86 При использовании формата списка выводится больше сведений о каждой службе, чем в формате таблицы (вместо трех столбцов данных о каждой службе в формате списка выводятся девять строк данных). Однако это вовсе не означает, что командлет Format-List извлекает дополнительные сведения о службах. Эти данные содержатся в объектах, возвращаемых командлетом Get-Service , однако командлет Format- Table , используемый по умолчанию, отбрасывает их, потому что не может вывести на экран более трех столбцов. При форматировании вывода с помощью командлетов Format- List и Format-Table можно указывать имена свойства объекта, которые должны быть отображены (напомним, что просмотреть список свойств, имеющихся у объекта, позволяет рассмотренный ранее командлет Get-Member ). Например: PS C:\> Get-Service | Format-List Name, Status, CanStop Name : Alerter Status : Stopped CanStop : False Name : ALG Status : Running CanStop : True Name : AppMgmt Status : Stopped CanStop : False Вывести все имеющиеся у объектов свойства можно с помощью параметра * , например: PS C:\> Get-Service | Format-table * 1.12.2 Перенаправление выводимой информации В оболочке PowerShell имеются несколько командлетов, с помощью которых можно управлять выводом данных. Эти командлеты начинаются со слова Out , их список можно получить с помощью команлета: PS C:\> Get-Command out-* | Format-Table Name Name ---- Out-Default Out-File Out-Host 87 Out-Null Out-Printer Out-String По умолчанию выводимая информация передается командлету Out- Default , который, в свою очередь, делегирует всю работу по выводу строк на экран командлету Out-Host . Для понимания данного механизма нужно учитывать, что архитектура PowerShell подразумевает различие между собственно ядром оболочки (интерпретатором команд) и главным приложением (host), которое использует это ядро. В принципе, в качестве главного может выступать любое приложение, в котором реализован ряд специальных интерфейсов, позволяющих корректно интерпретировать получаемую от PowerShell информацию. В нашем случае главным приложением является консольное окно, в котором мы работаем с оболочкой, и командлет Out-Host передает выводимую информацию в это консольное окно. Параметр Paging командлета Out-Host , подобно команде more интерпретатора Cmd.exe, позволяет организовать постраничный вывод информации, например: Get-Help Get-Process –Full | Out-Host –Paging |