如何使用调用表达式在模板中使用运行命令?



我正在为 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 '.Arista1AristaBase.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

编辑:顺便说一句,还有另一种不使用调用表达式的方法向我提出。(无论我走到哪里,都有人说使用不安全。但是,此其他方法仅替换文本。 我需要一种编辑文本模板的方法,该方法允许我对生成的文本执行一些命令。

例如,我需要一个 ForEach 循环,它采用以下模板文本:

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
  • 确实,应该避免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

一个简单的演示,您也可以在循环中使用该技术,并在按需扩展中使用当时的变量值:

$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

这是我针对您拥有的不同方案推荐的。

注意:您不应该使用 Invoke-Expression,但我想根据您之前的请求传递信息,您想看看如果您不使用 -replace它会如何工作。我提供了在使用Invoke-Expression之前应考虑-replace

1. 替换两个索引项

可以使用字符串上的-replace方法替换这两个索引项。对于这些示例,您可以使用 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:tempreplaced.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:tempreplaced.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

最新更新