IP address need to replace in text file

Welcome Forums General PowerShell Q&A IP address need to replace in text file

Viewing 9 reply threads
  • Author
    Posts
    • #176362
      Participant
      Topics: 1
      Replies: 11
      Points: 59
      Rank: Member

      Hi All,

      i have created a script to replace the IP address on the multiple files. Script will get the user Input IP address and find the in the text file and replace an new IP address. When i try to replace the IP address, its not replacing properly with match condition.

      $server = Get-Content "F:\Scripts\Replace_DNS_IP\server.txt"
      $_DNSList = @()
      
      #Get the input from the user
      $_DNSList = New-Object System.Net.IPAddress(0x1521A8C0)
      
      $_DNSList = READ-HOST "Enter the DNS Servers IP address(use , comma for addditional IPs )"
      #$_DNSList = $_DNSListip.Split(',').Split(' ')
      #splitting the list of input as array by Comma & Empty Space
      $_DNSList = $_DNSList.Split(',').Split(' ')
      
      $_ReplaceDNSList = @()
      $_ReplaceDNSList = New-Object System.Net.IPAddress(0x1521A8C0)
      #Get the input from the user
      $_ReplaceDNSList = READ-HOST "Enter the Replace DNS Servers IP address(use , comma for addditional IPs )"
      #$_ReplaceDNSList =$_ReplaceDNSListip.Split(',').Split(' ')
      
      #splitting the list of input as array by Comma & Empty Space
      $_ReplaceDNSList = $_ReplaceDNSList.Split(',').Split(' ')
      
      foreach ($input in $server) {
      
          $LogPath = Get-Item "F:\Scripts\Replace_DNS_IP\PSD Backup\$input.psd1"
      
          $Lines = Get-Content $LogPath | Where-Object {$_ -match "DNSServerAddress"}
      
          Foreach ($Line in $Lines) {
      
              #$IP =@()
              #$ip = New-Object System.Net.IPAddress(0x1521A8C0)
              $IP = ($Line | Select-String -Pattern "\d{1,3}(\.\d{1,3}){3}" -AllMatches).Matches.Value
      
              foreach ($IPs in $IP) {
                  if ($IPs -match $_DNSList[0]) {
                      Write-Host "Replacing DNS1"
                      (Get-Content -Path $LogPath).Replace($IPs, $_ReplaceDNSList[0]) | Set-Content -Path $LogPath
                  }
                  elseif ($IPs -match $_DNSList[1]) {
                      Write-Host "Replacing DNS2"
                      (Get-Content -Path $LogPath).Replace($IPs, $_ReplaceDNSList[1]) | Set-Content -Path $LogPath
                  }
                  elseif ($IPs -match $_DNSList[2]) {
                      Write-Host "Replacing DNS3"
                      (Get-Content -Path $LogPath).Replace($IPs, $_ReplaceDNSList[2]) | Set-Content -Path $LogPath
                  }
                  #elseif($IPs -match $_DNSList[3])
                  {
                      Write-Host "Replacing DNS4"
                      (Get-Content -Path $LogPath).Replace($IPs, $_ReplaceDNSList[3]) | Set-Content -Path $LogPath
                  }#>
                  else
                  {
                      Write-Host "DNS IP address is not Matching with Input"
                  }
              }
          }
      }
      

      Output of the script

      Via the script am replacing 3 IP address in text file. for example Source IP{8.8.8.8,4.4.4.4,5.5.5.5}

      1. if i try to replace 8.8.8.8,5.5.5.5, script will replace the new IP address, but 4.4.4.4 will be changed to blank " "
      2. if i try to replace 4.4.4.4, script is replacing only first number of the IP address"1" inside of "198.166.1.1

      Kindly help me to fix it.

      Thanks & Regards

      Manikandan.K

    • #176734
      Participant
      Topics: 1
      Replies: 11
      Points: 59
      Rank: Member

      Hi All,

      i have fixed the blank space replacement issue. But am facing during Single IP address replacement. If i provide the Single IP address, i was replacing entire IP address on the text file

    • #176836
      Participant
      Topics: 10
      Replies: 117
      Points: 457
      Helping Hand
      Rank: Contributor

      Manikandan.K,

      It would help if you could post your revised code. In the meantime, some suggestions for your code:

      1. It is not ideal to use $_ as a variable prefix because it's too close to the $psitem/$_ used in loops/error handing
      2. You'd want to consider refactoring the foreach statement (similar to below) for logic to make more sense and the code easier to read:
        $IPAddresses = ($Line | Select-String -Pattern "\d{1,3}(\.\d{1,3}){3}" -AllMatches).Matches.Value
        # previously $IP = ($Line ...
        
        foreach ($IP in $IPAddresses) {
            ...
        }
      3. Replace all the if/elseif statements with one switch statement:
        # inside foreach ($IP in IPAddresses)
        
        switch ($IP) {
            { $_ -match $_DNSList[0] } {
                Write-Host "Replacing DNS1"
                (Get-Content -Path $LogPath).Replace($_, $_ReplaceDNSList[0]) | Set-Content -Path $LogPath
            }
            { $_ -match $_DNSList[1] } {
                Write-Host "Replacing DNS2"
                (Get-Content -Path $LogPath).Replace($_, $_ReplaceDNSList[1]) | Set-Content -Path $LogPath
            }
            ...
        }
      • #178044
        Participant
        Topics: 1
        Replies: 11
        Points: 59
        Rank: Member

        Hi Aaron,

        Kindly fine the below revised code. And also i will check you code too.

        $server = Get-Content "F:\Scripts\Replace_DNS_IP\server.txt"
        
        $regex = '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'
        
        $_DNSList= @()
        
        #Get the input from the user
        $_DNSList = New-Object System.Net.IPAddress(0x1521A8C0)
        $_DNSList = READ-HOST "Enter the DNS Servers IP address(use , comma for addditional IPs )"
        
        #splitting the list of input as array by Comma & Empty Space
        $_DNSList = $_DNSList.Split(',').Split(' ')
        
        $_ReplaceDNSList= @()
        $_ReplaceDNSList = New-Object System.Net.IPAddress(0x1521A8C0)
        
        #Get the input from the user
        $_ReplaceDNSList= READ-HOST "Enter the Replace DNS Servers IP address(use , comma for addditional IPs )"
        
        #splitting the list of input as array by Comma & Empty Space
        $_ReplaceDNSList = $_ReplaceDNSList.Split(',').Split(' ')
        
        foreach($input in $server)
        {
        
        $LogPath = Get-Item "F:\Scripts\Replace_DNS_IP\PSD Backup\$input.psd1"
        
        $Lines = Get-Content $LogPath | Where-Object {$_ -match "DNSServerAddress"}
        
        Foreach ($Line in $Lines)
        
        {
        
        $IPs = ($Line | Select-String -Pattern $regex -AllMatches).Matches.Value
        
        foreach($IP in $IPs)
        
        {
        
        if(($IP -match $_DNSList[0]) -and ($_ReplaceDNSList[0] -ne $null))
        {
        Write-Host "Replacing $IP DNS Address to $_ReplaceDNSList[0] Address "
        (Get-Content -Path $LogPath).Replace($IP,$_ReplaceDNSList[0]) | Set-Content -Path $LogPath
        }
        elseif(($IP -match $_DNSList[1]) -and ($_ReplaceDNSList[1] -ne $null))
        {
        Write-Host "Replacing $IP DNS Address to $_ReplaceDNSList[1] Address"
        (Get-Content -Path $LogPath).Replace($IP,$_ReplaceDNSList[1]) | Set-Content -Path $LogPath
        }
        elseif(($IP -match $_DNSList[2]) -and ($_ReplaceDNSList[2] -ne $null))
        {
        Write-Host "Replacing $IP DNS Address to $_ReplaceDNSList[2] Address"
        (Get-Content -Path $LogPath).Replace($IP,$_ReplaceDNSList[2]) | Set-Content -Path $LogPath
        }
        elseif(($IP -match $_DNSList[3]) -and ($_ReplaceDNSList[3] -ne $null))
        {
        Write-Host "Replacing $IP DNS Address to $_ReplaceDNSList[3] Address "
        (Get-Content -Path $LogPath).Replace($IP,$_ReplaceDNSList[3]) | Set-Content -Path $LogPath
        }
        else
        {
        Write-Host "DNS IP address is not Matching with provided Input"
        }
        }
        
        }
        }
    • #178272
      Senior Moderator
      Topics: 8
      Replies: 1141
      Points: 3,927
      Helping Hand
      Rank: Community Hero

      @manikandank8286 – please use code formatting tags or use gist.github.com to post code in the forums.

      https://powershell.org/forums/topic/read-me-before-posting-youll-be-glad-you-did/

    • #178470
      Participant
      Topics: 10
      Replies: 117
      Points: 457
      Helping Hand
      Rank: Contributor

      After reviewing your inquiry again, there's a bit of repurposing of variables which can make code harder to follow.

      What is the difference between F:\Scripts\Replace_DNS_IP\server.txt and $LogPath = Get-Item "F:\Scripts\Replace_DNS_IP\PSD Backup\$input.psd1" ? Can you provide samples from both? What is the purpose of both files? .psd1 is normally a PowerShell module manifest file, and not used for logging.

      Are you open to users using an advanced function instead of manually typing IPs with commas? It would take care of the input validation for you.

    • #178512
      Participant
      Topics: 1
      Replies: 11
      Points: 59
      Rank: Member

      Hi Aaron,

      We are using Powershell DSC and SMA servers to build the Windows 2016 servers. All the information(CPU, memory, IP address, storage etc) about the server will be in *.psd1 file. *.psd1 file name will be the server name. i want to update the DNS IP address on more than  50 servers at a time. To avoid the manual work to update the DNS IP address in *.psd1 file, trying to develop a script. Server.txt will have the server name. i have updated the files on the GitHub for your reference https://github.com/Manik8286/Powershellscripts.git.

       

    • #179724
      Participant
      Topics: 10
      Replies: 117
      Points: 457
      Helping Hand
      Rank: Contributor

      Thanks for the details. Sorry for the delay as I've been in the midst of a deployment.

      While this could be more solidified (and some .NET), this script would work.

      It's an advanced function that takes the file path (.psd1), the IPs you want to replace in it, and the new IPs. If "DNSServerAddress" does not exists in the file, the file will be skipped.

      Otherwise, each old IP is replaced with the new one based their matching index (in the parameter arguments). Below, 4.4.4.4 is replaced by 192.168.10.1, and so on.

      The code after the function automates the process for all servers. In the splat, the specified Confirm = $false will run the script without the user being prompted to confirm the changes for each file update. Without this, you'll be prompted for each server. The final output shows what IPs were 'replaced' in which files.

      function Invoke-DNSServerAddressUpdate {
          [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
          param (
              [Parameter(Mandatory)]
              [ValidateScript( { Test-Path -Path $_ } )]
              [System.IO.FileInfo]
              $FilePath,
      
              [Parameter(Mandatory)]
              [ipaddress[]]
              $IPAddress,
      
              [Parameter(Mandatory)]
              [ipaddress[]]
              $NewIPAddress
          )
      
          if ($NewIPAddress.Count -ne $IPAddress.Count) {
              Write-Error "IP count mismatch" -ErrorAction Stop
          }#if
      
          $psd1Content = Get-Content -Path $FilePath
      
          # Check if "DNSServerAddress =" exists in file, ignore if it doesn't
          if ($psd1Content -match "DNSServerAddress\s?=") {
      
              # Counter for matching indexes of IPAddress to NewIPAddress
              $counter = 0
      
              foreach ($ip in $IPAddress) {
                  # Update content by replacing IPAddress(es) with NewIPAddress(es)
                  $oldIP       = $ip.IPAddressToString
                  $newIP       = $NewIPAddress[$counter].IPAddressToString
                  $psd1Content = $psd1Content -replace $oldIP, $newIP
                  $counter    += 1
      
                  [pscustomobject]@{
                      FilePath = $FilePath.FullName
                      OldIPAddress = $oldIP
                      NewIPAddress = $newIP
                  }
              }#foreach
      
              if ($PSCmdlet.ShouldProcess("Update IP Address(es) in $FilePath")) {
                  $psd1Content | Set-Content -Path $FilePath -Force
              }#if
          }#if
      }#function
      
      
      # Run against all servers
      $parentPath  = './Powershellscripts-master'
      
      # Get server names
      $serverNames = Get-Content -Path (Join-Path -Path $parentPath -ChildPath server.txt)
      
      # Get server.psd1 paths
      $serverFiles = $serverNames | ForEach-Object { Join-Path $parentPath -ChildPath "$_.psd1" }
      
      # In all files, replace old IPs with new ones
      foreach ($file in $serverFiles) {
          $params = @{
              FilePath     = $file
              IPAddress    = '4.4.4.4', '5.5.5.5', '8.8.8.8'
              NewIPAddress = '192.168.10.1', '192.168.10.7', '192.168.10.10'
              Confirm      = $false # do not prompt to overwrite files
          }
      
          Invoke-DNSServerAddressUpdate @params
      }#foreach
      • #179826
        Participant
        Topics: 1
        Replies: 11
        Points: 59
        Rank: Member

        Thanks for support to fix the issue with Advance function to replace the single IP address and multiple IP address.  Script is going to use more the 10 person. So i planned to get the IP address via command line input, dont want to modify the IP address in script. Below line need to change in script as user input. How can i proceed in Hashing Array.

        IPAddress = '4.4.4.4', '5.5.5.5', '8.8.8.8'
        NewIPAddress = '192.168.10.1', '192.168.10.7', '192.168.10.10'

        Thanks & Regards

    • #179955
      Participant
      Topics: 10
      Replies: 117
      Points: 457
      Helping Hand
      Rank: Contributor

      Just use the function and not the code below it (which was meant for predefining IPs and just running it against every file).

      For the more interactive style, dot-sourcing the .ps1 file allows you to enter one IP per prompt:

      PS />. ./Invoke-DNSServerAddressUpdate.ps1
      PS />Invoke-DNSServerAddressUpdate -FilePath ./server200.psd1
      ...
      IPAddress[0]: 4.4.4.4
      IPAddress[1]:
      NewIPAddress[0]: 192.168.10.4
      NewIPAddress[1]:
      ...
      
      (Output shown here)

      The output shows what IPs would have been replaced by new IPs, like a history, and not just what was actually replaced in the file.

      • #180123
        Participant
        Topics: 1
        Replies: 11
        Points: 59
        Rank: Member

        Hi Aaron,

        Am able to replace the IP address on single file. Not able to update in multiple *.psd file. File is updating only  last entry of the server.txt.

         

    • #179964
      Participant
      Topics: 10
      Replies: 117
      Points: 457
      Helping Hand
      Rank: Contributor

      And an oversight on my part... Though you may not need it at the moment, the splat starting on line 37 should be:

      [pscustomobject]@{
          FilePath     = Convert-Path -Path $FilePath # not FilePath.FullName
          OldIPAddress = $oldIP
          NewIPAddress = $newIP
      }
      • #180126
        Participant
        Topics: 1
        Replies: 11
        Points: 59
        Rank: Member

        Hi Aaron,

        Am able to replace the IP address on single file. Not able to update in multiple *.psd file. File is updating only  last entry of the server.txt.

      • #180420
        Participant
        Topics: 1
        Replies: 11
        Points: 59
        Rank: Member

        Hi,

        Made some changes in Code and now its working as expected. Thanks for your help.

        
        function Invoke-DNSServerAddress {
        [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
        param (
        
        [Parameter(Mandatory)]
        [ipaddress[]]
        $IPAddress,
        
        [Parameter(Mandatory)]
        [ipaddress[]]
        $NewIPAddress
        )
        
        $server = Get-Content "F:\Scripts\Replace_DNS_IP\server.txt"
        
        foreach($input in $server)
        {
        Write-Host "*******Backing Up the file**********" -ForegroundColor DarkRed
        Copy-Item -Path "Z:\MachineData.Current\$input.psd1" -Destination "F:\Scripts\Replace_DNS_IP\PSD Backup"
        $LogPath = Get-Item "Z:\MachineData.Current\$input.psd1"
        #$LogPath = Get-Item "F:\Scripts\Replace_DNS_IP\PSD Backup\$input.psd1"
        
        $Lines = Get-Content -Path $LogPath
        
        if ($Lines -match "DNSServerAddress\s?=") {
        
        # Counter for matching indexes of IPAddress to NewIPAddress
        $counter = 0
        
        foreach ($ip in $IPAddress) {
        # Update content by replacing IPAddress(es) with NewIPAddress(es)
        $oldIP = $ip.IPAddressToString
        $newIP = $NewIPAddress[$counter].IPAddressToString
        $Lines = $Lines -replace $oldIP, $newIP
        $counter += 1
        
        [pscustomobject]@{
        FilePath = $LogPath#.FullName
        OldIPAddress = $oldIP
        NewIPAddress = $newIP
        WrittenTime = get-item "$LogPath" | select -Property Lastwritetime
        }
        
        }
        if ($PSCmdlet.ShouldProcess("Update IP Address(es)")) {
        $Lines | Set-Content -Path $LogPath -Force
        }
        }
        }
        
        }Invoke-DNSServerAddress
        
        

        Thanks & Regards

        Manikandan.K

    • #180492
      Participant
      Topics: 10
      Replies: 117
      Points: 457
      Helping Hand
      Rank: Contributor

      Excellent, glad it works (and sorry for delays).

Viewing 9 reply threads
  • You must be logged in to reply to this topic.