Powershell для сохранения значения регулярного выражения в переменной и построения строки - PullRequest
1 голос
/ 12 апреля 2019

Я хотел бы получить значение из различных регулярных выражений, чтобы создать список файлов моих проверок работоспособности конечной точки.

У меня есть несколько сценариев PS, которые правильно анализируют и извлекают информацию из некоторых текстовых файлов, но яЯ хочу использовать значения, записанные в различных регулярных выражениях в моем скрипте, для создания новых строк.

Мой скрипт ниже читает из текстового файла # 1 и из выходного текстового файла # 2, все правильно.

PSСкрипт

(Get-Content 'c:\fake_path\test_stack.txt') `
      | Select-String '(^\S{5}SERVER:)(\S*)(\S{5})','(^\S*n:\"\*:)(\d*)(:"\s$)','(^\"\/)(\S*)("\s$)' -AllMatches | Foreach-Object {$_.Matches} | 
       Foreach-Object {$_.Groups[2].Value} |
       Out-File c:\fake_path\demo_stack.txt

1 InFile

*****SERVER:WIN001*****
SITE.NAME:"PRJ_ABC"
bindingInformation:"*:80:" 
"/App001" 
*****SERVER:WIN002*****
SITE.NAME:"PRJ_DEF"
bindingInformation:"*:81:" 
"/App001" 
SITE.NAME:"PRJ_HIJ"
bindingInformation:"*:82:" 
"/App001" `

2 OutFile

WIN001
80
App001
WIN002
81
App001
82
App001`

Однако я надеюсь использовать значения, которые записаны в моих 3 различных регулярных выражениях нижев 3 различных переменных, скажем, $ a, $ b и $ c.

(Select-String '(^\S{5}SERVER:)(\S*)(\S{5})','(^\S*n:\"\*:)(\d*)(:"\s$)','(^\"\/)(\S*)("\s$)')

Моя попытка:

Foreach-Object 'http://' + 'a.{$_.Groups[2].Value}' + ':' + '$b.{$_.Groups[2].Value}' + '/' + '$c.{$_.Groups[2].Value}' + '/api/status'

Желаемыйвывод моей попытки (написано выше)

Новый файл, составленный так: http://WIN001:80/App001/api/status http://WIN002:81/App001/api/status http://WIN002:81/App001/api/status Итак, как вы можете видеть, я хотел записать регулярное выражение в переменных $ a $ b и $ c, а затем объединить строки, такие как http: // + $ a + ':' + $ b + ..... и т. д. для того, чтобы отформатировать его и создать URL.

Я считаю, что это возможно, просто не хватает фона.

Приветствую все советы, ура; -)

Ответы [ 2 ]

3 голосов
/ 12 апреля 2019

Я придерживаюсь более простого подхода,

  • каждая строка ввода проверяется по 3 довольно простым регулярным выражениям с именованными группами захвата,
  • если первые 1 совпадают, переменная установлена,
  • если последний сопоставляет URL с собранными данными, выводится:

## Q:\Test\2019\04\12\SO_55655078.ps1

(Get-Content '.\test_stack.txt')| ForEach-Object {
    if($_ -match 'SERVER:(?<server>[^*]+)'){$Server = $Matches.Server}
    if($_ -match ':(?<port>\d{2,5}):'     ){$Port   = $Matches.Port}
    if($_ -match '^\"(?<App>[^"]+)\"'     ){
       "http://{0}:{1}{2}/api/status" -f $Server,$Port,$Matches.App
    }
} # | Set-Content '.\demo_stack.txt'

Пример вывода:

> Q:\Test\2019\04\12\SO_55655078.ps1
http://WIN001:80/App001/api/status
http://WIN002:81/App001/api/status
http://WIN002:82/App001/api/status

Кстати, ваша третья строка примера неверна, она должна иметь порт 82.

3 голосов
/ 12 апреля 2019

Это немного некрасиво, но работает:

$file = Get-Content "c:\somefile.txt" -Raw
ForEach ($entry in ($file -split "(?m)^\*{5}").trim()) {
    $server = (Select-String -InputObject $entry -Pattern "(?m)(?<=SERVER:)(?<Server>.*?)(?=\*+.*$)" -AllMatches).matches.value -as [array]
    $ports = (Select-String -InputObject $entry -Pattern "(?m)(?<=:`".*?:)(?<port>\d+)(?=:`".*$)" -AllMatches).matches.value -as [array]
    $apps = (Select-String -InputObject $entry -Pattern "(?m)(?<=^`")(?<app>/.*?)(?=`".*$)" -AllMatches).matches.value -as [array]
    for ($i = 0; $i -lt $ports.count; $i++) {
        "http://" + $server + ":" + $ports[$i] + $apps[$i] + "/api/status" | Out-File -FilePath "NewFile.txt" -Append
    }
}

Я использовал метод -Split, чтобы разделить файл на записи сервера. Каждая из этих записей является элементом массива, который хранится в $entry во время итерации цикла. Я делю на соответствие любой строке, которая начинается с 5 * символов (^\*{5}). Метод .trim() просто удаляет пустые строки в середине разделенного вывода.

$server - массив, которому сопоставлен текст из записи, представляющей имя сервера.

  • (?m) - многострочный модификатор. Это так, что ^ и $ будут соответствовать началу и концу каждой строки.
  • (?<=SERVER:) является положительным взглядом для начала сопоставления с позиции, которая следует за строкой SERVER: .
  • (?<Server>.*?) - это группа захвата с именем Server, которая содержит строку имени сервера.
  • (?=\*+.*$) - это положительный прогноз для одного или нескольких * символов, за которыми следуют любые символы и затем конец строки.

$ports - массив, которому назначены все номера портов в вашем атрибуте привязок.

  • (?<=:`".*?:) является положительным взглядом для : ", за которым следует несколько символов, а затем :
  • (?<port>\d+) - это именованный порт группы захвата, который представляет номер вашего порта
  • (?=:`".*$) - это положительный прогноз для : ", а затем любые символы до конца строки

$apps - массив, которому назначены все каталоги приложений, которые существуют в одной строке

  • (?<=^`") - положительный взгляд на строку, начинающуюся с "
  • (?<app>/.*?) - приложение группы захвата, которое представляет соответствующие пути приложения без кавычек. Он захватывает / и любые символы, пока не достигнет "
  • (?=`".*$) - это положительная проверка «за» после любых символов до конца строки

Цикл for предполагает, что существует столько номеров портов, сколько путей приложений на сервер. Причина, по которой каждая переменная выше является массивом, заключается в том, что к первому элементу [0] можно получить доступ с тем же синтаксисом, что и к любому другому элементу, когда может присутствовать только один элемент. Цикл выводит конкатенацию строк с каждой итерацией, потенциально выводя различные комбинации порта и пути приложения. Каждая строка выводится в NewFile.txt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...