Как использовать команды запуска внутри шаблона с помощью Invoke-Expression? - PullRequest
1 голос
/ 24 января 2020

Я создаю шаблон текстового файла для конфигураций переключателей Arista, и я только что разработал, как заменить переменные в моих шаблонах, используя Invoke-Expression.

Существующее решение прекрасно работает для сингулярных переменных, но у меня есть массивы, которые я хотел бы также использовать, и позже у меня будут некоторые циклы ForEach.

Мне нужно знать, как заставить этот метод фактически выполнять операции внутри моего шаблона, или, в качестве альтернативы, отредактировать «вызванное выражение» перед тем, как вывести его в файл.

Текущий фрагмент сценария:

#Variables
$peerlink1int = "49"
$stamps = @("208","209","210","211")

$filename = ('SwitchConfig' + $(get-date -f 'MM-dd-yyyy HH-mm'))
$destination_file = ".\$filename.txt"

$Base = Get-Content '.\Arista\01AristaBase.txt' | out-string
$revisedBase = Invoke-Expression "`"$Base`""
$revisedBase | Out-File -append $destination_file

Фрагмент исходного файла:

interface Ethernet $peerlink1int
   switchport trunk allowed vlan $Stamps[0]-$Stamps[-1],1111,1234

Результат вывода:

interface Ethernet 49
   switchport trunk allowed vlan 208 209 210 212[0]-208 209 210 211[-1],1111,1234

То, что я ожидал:

interface Ethernet 49
   switchport trunk allowed vlan 208-211,1111,1234

Редактировать: как кроме того, был предложен другой метод, который не использовал Invoke-Expression. (Везде, где я go кто-то говорит, что использовать небезопасно.) Однако этот другой метод просто заменяет текст. Мне нужен метод редактирования текстового шаблона, который позволяет мне выполнять некоторые команды с результирующим текстом.

Например, мне нужен ForEach l oop, который принимает текст шаблона:

interface Vlan$stamps
   description V$stamps
   ip address 192.168.$stamps.2/25
   vrrp $stampnum ip 192.168.$stamps.1
   vrrp $stampnum description Stamp$stamps

И выполняет цикл один раз для каждого элемента в массиве $ stamps, так что вы получите:

interface Vlan208
   description V208
   ip address 192.168.208.2/25
   vrrp $stampnum ip 192.168.208.1
   vrrp $stampnum description Stamp208

interface Vlan209
   description V209
   ip address 192.168.209.2/25
   vrrp $stampnum ip 192.168.209.1
   vrrp $stampnum description Stamp209

interface Vlan210
   description V210
   ip address 192.168.210.2/25
   vrrp $stampnum ip 192.168.210.1
   vrrp $stampnum description Stamp210

interface Vlan211
   description V211
   ip address 192.168.211.2/25
   vrrp $stampnum ip 192.168.211.1
   vrrp $stampnum description Stamp211

Ответы [ 2 ]

1 голос
/ 24 января 2020
  • Действительно, Invoke-Expression следует избегать .

  • Внутри расширяемых строк ("..."), только просто ссылки на переменные могут быть встроены напрямую (например, $stamps), чтобы встроить выражения - что включает в себя доступ к свойству и индексирование - необходимо заключить выражение в виде целое в $(...) (например, $($Stamps[0])) - см. этот ответ .

  • В конечном итоге вы ищете строковые шаблоны , которые PowerShell предоставляет - несколько неясно - через по требованию расширение дословных (буквальных) строк в виде расширяемых строк через $ExecutionContext.InvokeCommand.ExpandString().


# Define the string template - note the $(...) around
# $Stamps[0] and $Stamps[1]
$template = @'
interface Ethernet $peerlink1int
   switchport trunk allowed vlan $($Stamps[0])-$($Stamps[-1]),1111,1234
'@

# Define the variable referenced in the template
$stamps = '208', '209', '210', '211' # better than: @("208","209","210","211")

# Expand the template.
$revisedBase = $ExecutionContext.InvokeCommand.ExpandString($template)

$revisedBase теперь содержит следующее, чего вы ожидали:

interface Ethernet 
   switchport trunk allowed vlan 208-211,1111,1234

Простая демонстрация того, что Вы можете использовать технику в других oop, а также , с текущими значениями переменных, используемыми в расширении по требованию:

$template = '`$foo is now: $foo'

foreach ($foo in 1..3) {
  $ExecutionContext.InvokeCommand.ExpandString($template)
}

Вышеуказанные отпечатки:

$foo is now: 1
$foo is now: 2
$foo is now: 3
1 голос
/ 24 января 2020

Это то, что я бы порекомендовал для другого сценария ios, который у вас есть.

ПРИМЕЧАНИЕ : Вы не должны использовать Invoke-Expression, но я хотел передать информацию, основанную на вашем предыдущем запросе, где вы хотели посмотреть, как она будет работать, если вы не используете - replace. Я предоставляю -replace, который следует учитывать, прежде чем использовать Invoke-Expression.

1. Заменить два проиндексированных элемента

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

$stampArray = @("208","209","210","211")
$peerlink1int = "49"
$template = 'interface Ethernet $peerlink1int
   switchport trunk allowed vlan $Stamps[0]-$Stamps[-1],1111,1234'
#OR $template = Get-Content Your-File | Out-String

# You have to escape not only $, but also [ and ].
$template -replace '\$peerlink1int', $peerlink1int `
            -replace '\$Stamps\[0\]', $stampArray[0] `
            -replace '\$Stamps\[-1\]', $stampArray[-1] `
            | Out-File C:\temp\replaced.txt

или

# Invoke-Expression can only work if your variable is covered with $() to include indecies 
$peerlink1int = "49"
$stamps = @("208","209","210","211")
$template = 'interface Ethernet $peerlink1int
   switchport trunk allowed vlan $($Stamps[0])-$($Stamps[-1]),1111,1234'
$result = Invoke-Expression "`"$template`""

Вывод , который вы получаете из обоих приведенных выше примеров:

interface Ethernet 49
   switchport trunk allowed vlan 208-211,1111,1234

2. Замените несколько значений из массива

. Есть два способа сделать это. 1 - это Invoke-Expression, который может вызывать опасные выражения в вашем скрипте, а другой - это -replace метод.

$stampArray = @("208","209","210","211")
$template = 'interface Vlan$stamps
   description V$stamps
   ip address 192.168.$stamps.2/25
   vrrp $stampnum ip 192.168.$stamps.1
   vrrp $stampnum description Stamp$stamps'

# Using Invoke-Expression
$stampnum = 1
$result = @()
foreach($stamps in $stampArray) {
    $result += Invoke-Expression "`"$template`"" #$stamps and $stampnum will be replaced in the document.
    $stampnum ++
}

# Or you can do with the replace command
$stampnum = 1
$result = @()
foreach($stamps in $stampArray) {
    $result += $template -replace '\$stamps', $stamps -replace '\$stampnum', $stampnum++
}

$result | Out-File C:\temp\replaced.txt

И, Вывод , который вы получите,

interface Vlan208
   description V208
   ip address 192.168.208.2/25
   vrrp 1 ip 192.168.208.1
   vrrp 1 description Stamp208
interface Vlan209
   description V209
   ip address 192.168.209.2/25
   vrrp 2 ip 192.168.209.1
   vrrp 2 description Stamp209
interface Vlan210
   description V210
   ip address 192.168.210.2/25
   vrrp 3 ip 192.168.210.1
   vrrp 3 description Stamp210
interface Vlan211
   description V211
   ip address 192.168.211.2/25
   vrrp 4 ip 192.168.211.1
   vrrp 4 description Stamp211
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...