-replace

Многие знают про оператор -Replace в PowerShell. Ну как минимум те, кто читал документацию🙂 Тут я перечислю несколько интересных вариантов его применения.

Начну как всегда с простого🙂

PS C:\PowerShell> "SimpleShell" -replace "Simple","Power"
PowerShell

Синтаксис оператора немного необычен для PowerShell. Слева ставится текст в котором производится замена, а в правой части массив из двух элементов. Первый из них это регулярное выражение обозначающее «что» будет заменено, а второй — то «на что» будет заменено. Как результат сравнения оператор выдает измененный объект.

Кстати объектом может быть не только строка, но и массив строк:

PS C:\PowerShell> $arr = "test1","test2","test3"
PS C:\PowerShell> $arr = $arr -replace "[a-z]","."
PS C:\PowerShell> $arr
....1
....2
....3

Тут я применил простое регулярное выражение заменяющее любую букву из диапазона a-z, на точку. Оператор -replace отработал все строки из массива, и вернул его в исходном виде, но без букв. Они мне давно не нравились.

Ну и конечно таким образом можно заменить содержимое целого файла:

PS C:\PowerShell> (Get-Content .\log.txt) -replace "txt","exe" | Set-Content log.txt

Есть одна хитрость о которой документация умалчивает:

Из этих примеров следует, что оператор -replace используется также, как и
любой другой оператор сравнения, за исключением того, что после оператора
необходимо указывать два значения. В первом значении указываются заменяемые

Это не совсем так, можно указывать и одно значение🙂 Правда тогда -replace превращается в… -remove😉

PS C:\PowerShell> "необходимо указывать два значения." -replace "[аи]"
необходмо укзывть дв знченя.

Например так из строки удаляются все вхождения букв «а» и «и».

По умолчанию все сравнения строк в PowerShell производятся игнорируя регистр символов. Для того чтобы принимать его во внимание достаточно приставить к оператору сравнения букву «c» — Case sensetive. Так -eq становится -ceq а -like и -match соответственно -clike и -cmatch. Ну и с -replace работает то же правило:

PS C:\PowerShell> "AaBbCcDdEe" -creplace "[A-Z]"
abcde

Никто не мешает использовать оператор несколько раз:

PS C:\PowerShell> "AaBbCcDdEe" -creplace "[A-Z]" -replace "^." -replace ".$"
bcd

Так я пользуясь случаем не только избавился от всех заглавных букв, но и удалил первую и последнюю буквы. Для тех кто только сейчас проникается мощью регэкспов поясню, — «^» обозначает начало строки, «$» — конец, а точка — один любой символ.

Для знакомых с регулярными выражениями будет интересно узнать что во втором элементе можно использовать «захваченные группы» (не знаю как правильно по-русски🙂 ). А захватываются они соответственно с помощью первого элемента:

PS C:\PowerShell> "<b>Text</b><i>test</i>" -replace "\<(.+?)\>",'[$1]'
[b]Text[/b][i]test[/i]

Тут я поместил содержимое тегов в группу (группы в регулярных выражениях обозначаются скобками), которую затем применил во втором элементе массива. Если вы не сталкивались раньше с регулярными выражениями то это и должно выглядеть очень непонятно🙂 Это нормально — знаю по себе🙂 Кстати я тут не просто так поместил второй элемент в одинарные кавычки — ‘[$1]’. Если бы они были двойными, то PowerShell попытался бы вычислить переменную $1 еще до выполнения команды, и подсунул бы на её место «» (так как эта переменная не объявлена). Короче говоря ничего. И прощай содержимое тегов🙂

Таким образом можно захватывать несколько групп, и использовать их. Это дает нам много интересных применений, например команда -double🙂

PS C:\PowerShell> "побитовые операторы не возвращают значения" -replace "[оеи]",'$0$0'
пообиитоовыее оопеератооры нее воозвращают значеениия

Думаю вы догадались что группа $0 обозначает всё попавшее под маску содержимое, в данном случае буквы «о», «е», и снова «и»🙂

Ну и хороший практический пример. Мне очень часто приходится получать данные из всевозможных источников, и не менее часто в этих данных присутствуют значения времени, дат, и т.п. Ну и конечно во всевозможных форматах. И конечно мне хочется работать со всеми этими данными используя возможности PowerShell. Но…

Если повезет то дата преобразовывается в формат [DateTime] с лёту (для этого она должна быть отформатирована по правилам северной америки):

PS C:\PowerShell> [datetime]$d = "04.02.2008 16:25:32"
PS C:\PowerShell> $d.AddMonths(1)
2 апреля 2008 г. 16:25:32

А дата например в формате типа «16:25:32#02-04-2007»? Мало того что месяц и число в другом порядке, так еще и разделители «-«, да и время почему то впереди и отделено «#»… Подумаешь… У нас есть -replace, он и форматы времени меняет😉

PS C:\PowerShell> [datetime]("16:25:32#02-04-2008" -replace "(.+)#(\d+)-(\d+)-(\d+)",'$3.$2.$4 $1')
2 апреля 2008 г. 16:25:32

Ну и поясню регулярное выражение: «.+» — это один или более экземпляров любого символа, а «\d+» — одна или более цифр. Если разобрать на части дальше — «\d» обозначает любую цифру, а знак «+» указывает что надо взять 1 или более предыдущих элементов.

комментариев 5 to “-replace”

  1. isa Says:

    А где можно доку по регулярным выражениям найти желательно внятныю и на русском?

  2. Xaegr Says:

    2 isa:
    Я вот с этого начинал — http://phpclub.ru/detail/article/regexp_1
    Тут конечно только основы, но ничего лучше я на русском языке не находил.
    Краткую сводку можно посмотреть в PoSh’е так: get-help about_regular_expression
    В планах (далёких) написать толковую статью о регэкспах в PowerShell + примеры популярных задач.

  3. T Says:

    Я осваивал вот по этой книге
    http://www.ozon.ru/context/detail/id/2142281/
    Недорогая , небольшая , понятная и реально охватывает весь необходимый спектр практических применений . Это как раз тот случай , когда больше и не надо

  4. Scripting Games: Sudden Death Challenge - Events 8 & 9 « PowerShell и другие скрипты Says:

    […] оператор -replace с простеньким выражением (все символы кроме букв a-z, […]

  5. Парсинг дат и времени « PowerShell и другие скрипты Says:

    […] эту строку, и сконвертировать её в тип DateTime? В посте про оператор -replace я уже показывал один из вариантов […]


Обсуждение закрыто.

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