3

I have a number of .txt files that I use as standardized templates for Arista switch deployments, but I want to update them rapidly using PowerShell. I replaced all the necessary values in these templates with $variables and I now am attempting to write a script to replace them.

I found a solution that I liked, but it is not working for me. I am not sure what I am doing wrong here. https://stackoverflow.com/a/9326779/

This is a snippet from the source file :

router bgp $asn
   router-id 10.1.1.1
   bgp listen range 192.168.$id.0/25 peer-group cluster$id remote-as $asn
   neighbor cluster$id peer-group
   neighbor cluster$id update-source Loopback0
   neighbor cluster$id description cluster$id-BGP
   neighbor cluster$id ebgp-multihop 3
   neighbor cluster$id maximum-routes 12000
   network 10.1.1.1/32
exit

Here is a snippet from the powershell script :

$newvars = @{
'$id' = '101'
'$asn' = '12345'
}

$template = '.\Arista\arista.txt'
$destination_file = '.\switchconfig' + $id + '.txt'

Get-Content -Path $template | ForEach-Object {
    $line = $_

    $newvars.GetEnumerator() | ForEach-Object {
        if ($line -match $_.Key)
        {
            $line = $line -replace $_.Key, $_.Value
        }
    }
   $line
} | Set-Content -Path $destination_file

What I want is to have a group of variables defined (upwards of 30), and then replace each instance of that variable in the text file with the value contained in the script. This solution seemed good, since it would avoid doing a "replace" over and over, but it just prints the file as it originally was.

n0ttsweet
  • 69
  • 1
  • 7
  • In addition to the accepted answer, I wrote a function that will step through a csv file and define veriables with the same name as the fields. It then generates one expansion of a template for each record in the csv. [answer to this question](https://stackoverflow.com/questions/74992818/generate-a-single-tmsl-file-for-all-records-in-the-excel-csv-file-in-powershell) – Walter Mitty Jan 15 '23 at 12:57

1 Answers1

1

Since powershell uses $ as an identifier for variables (reserved), you have to properly escape that when running your method. Following is a little off but does what you are looking for. update your dictionary with \ before your $ sign to replace text including $.

$newvars = @{
'\$id' = '101'
'\$asn' = '12345'
}

$template = "C:\temp\new.txt"
$destination_file = "C:\temp\replaced.txt"
$data = @()
foreach($line in Get-Content $template) {
    foreach($key in $newvars.Keys) {
        if ($line -match $key) {
            $line = $line -replace $key, $newvars[$key]
        }
    }
    $data += $line
}

$data | Out-File $destination_file

Another thing to note.. in your file you are defining $id as the name of the file. I am not sure where but that variable would always be null as its not defined yet (unless your snippet here is different from your actual code.

If you want to use Invoke-Expression, you can use it in the following way,

$id = '101'
$asn = '12345'

$template = (Get-Content "C:\temp\new.txt") | out-string
$data = Invoke-Expression "`"$template`""
$data | Out-File "C:\Temp\test.txt"

You'll have to make sure your variables ($id, $asn) have a value to replace when evaluating the variables within your text file.

Jawad
  • 11,028
  • 3
  • 24
  • 37
  • I see that mistake with the $id now, thank you. Originally, I just had a list of defined variables at the top. Another user commented that this solution may work and I could skip all the 'foreach' stuff. https://stackoverflow.com/a/1667774/ What do you think? – n0ttsweet Jan 23 '20 at 19:16
  • 1
    see the update @n0ttsweet – Jawad Jan 23 '20 at 19:35
  • Thanks for the update! If I could give you another upvote, I would! I think there is a mistake in the update though? `$data = Invoke-Expression "\`"$template\`""` I get an error at the part with ' " ". Should it be " ' " ? – n0ttsweet Jan 23 '20 at 20:06
  • 1
    I'm an idiot. I read the ` as a '. I forgot that it was the escape character for Powershell. It works perfect. – n0ttsweet Jan 23 '20 at 20:12
  • 1
    I'm glad you figured it out – Jawad Jan 23 '20 at 20:31
  • I had to switch over to using the Invoke-Expression method, because I need to treat the array values as actual variables. I need to use some of them as arrays or re-use them for other purposes. However, I am having a separate issue with Invoke-Expression does not respect something like $stamps[0]. It just prints the whole array. My other question, if you want to help :https://stackoverflow.com/questions/59887463/ – n0ttsweet Jan 23 '20 at 22:03
  • This is in addition to the correct answer. Expand-Csv is a function that combines a csv file with a template. [Look here](https://stackoverflow.com/questions/74992818/generate-a-single-tmsl-file-for-all-records-in-the-excel-csv-file-in-powershell) – Walter Mitty Jan 15 '23 at 12:59