Replacing Strings in Files Using PowerShell

Script fills void left from missing cmdlet

Bill Stewart

November 19, 2010

7 Min Read
Replacing Strings in Files Using PowerShell


Windows PowerShell provides native capabilities for string pattern matching and string replacement through its comparison operators. However, PowerShell doesn't have a native cmdlet for replacing strings of text in files, so I wrote the Replace-FileString.ps1 script to fill this void. After I show you how to take advantage of PowerShell's native capabilities, I'll show you how to use Replace-FileString.ps1.

PowerShell's Native Capabilities

PowerShell's -like, -match, and -replace operators make matching and replacing strings much more accessible to nonprogrammers. PowerShell's command line provides users with the ability to experiment with .NET regular expressions with greater ease than with traditional scripting languages. A regular expression (sometimes referred to as regex) is a string that contains special characters or character sequences that represent other characters or character sequences. Regular expressions are similar to wildcard patterns but are much more expressive. If you're not familiar with regular expressions, the PowerShell Help topic about_regular_expressions can help you get started learning about them. To view the help topic, type

Get-Help about_regular_expressions

at a PowerShell prompt.

An obvious application for regular expressions is to replace strings in files. For example, suppose you want to extract only the computer names from the output of the Net View command. If you run the command

Net View > List.txt

then open the List.txt file in Notepad, you'll notice all kinds of extraneous information such as column headings, extra spaces at the end of each line, and a footer line that tells you the command completed successfully. Using regular expressions in PowerShell, you can extract and output only the computer names. Take, for example, the command

Get-Content List.txt |  Where-Object \{ $_ -match '^\\' \} |  ForEach-Object \{ $_ -replace  '^\\(S+).+','$1' \}

(Although this command wraps here, you'd enter it all on one line in the PowerShell console. The same holds true for the other commands that wrap.) The Get-Content cmdlet retrieves each line in List.txt. The Where-Object cmdlet then uses the -match operator to check whether each line starts with two backslashes. If a line starts with two backslashes, it's passed to ForEach-Object cmdlet, which uses the -replace operator to output only the computer names.

Let's take a closer look at the -match operator, which is used with the pattern ^\\. The caret symbol (^) indicates that you want to match the beginning characters. Because the backslash is the escape character for regular expressions, you have to use two backslashes (\) to represent a single backslash (). Thus, you need to include a total of four backslashes. Table 1 describes this and other regular expression patterns used in this command.

Replace-FileString.ps1

When working with text files, it's often useful to be able to replace strings in a file using regular expressions, then write the results back to the original file. Because there isn't a PowerShell cmdlet that provides this functionality, I wrote Replace-FileString.ps1. It's a PowerShell equivalent to opening a file with Notepad, doing a find-and-replace operation, and saving the file. But unlike Notepad, you can use this script to replace strings in multiple files at the same time.

Replace-FileString.ps1 supports searching across line breaks because it uses the ReadAllText method of the Windows .NET Framework's System.IO.File class instead of the Get-Content cmdlet to read in text. Unlike Get-Content, which reads only one line of a file at a time, the ReadAllText method reads each file as a single string, so it can find strings across line breaks. (Because each file is one string, the script might run slow for very large files.)

Replace-FileString.ps1 requires PowerShell 2.0. The script's command-line parameters are listed in Table 2. In addition to the parameters listed in Table 2, the script also supports the -Confirm, -Verbose, and -WhatIf common parameters.

There are two required parameters: -Pattern and -Replacement. You also need to specify the file in which you want to find and replace strings. There are two ways you can do so. The first way is to use the -Path or -LiteralPath parameter in a command such as

Replace-FileString  -Pattern 'this'  -Replacement 'that'  -Path Test.txtReplace-FileString

Typically, you don't need to use the -LiteralPath parameter unless you need to specify a path or filename that contains characters that PowerShell normally interprets as wildcards. (Square braces, \[ \], are the usual culprits.)

The second way is to pipe file objects to the script by using a command such as

Get-Item Test.txt | Replace-FileString  -Pattern 'this'  -Replacement 'that'

To demonstrate how to use Replace-FileString.ps1, let's look at three sample applications. I'll show you how to use the script to convert Net View output to a comma-delimited list of computer names, replace data in .ini files, and replace an LDAP path in a set of scripts.

Sample Application 1

Suppose you need to convert Net View output to a comma-delimited list of computer names. To begin, you can use the Net View command combined with the -match and -replace operators to generate a list of computer names, like so

Net View | Where-Object \{ $_ -match '^\\' \} |  ForEach-Object \{  $_ -replace  '^\\(S+).+','$1' \} |  Out-File Computers.txt

(See Table 1 for the descriptions of the regular expression patterns.) The Computers.txt file now contains the computer names from the Net View command, one computer name per line. Next, you can have Replace-FileString.ps1 replace the newlines in the file with commas by using the command

Replace-FileString  -Pattern 'r'  -Replacement ','  -Path Computers.txt

This command replaces all r (carriage return and line feed) characters in the file with commas and outputs the file. If desired, you can add the -Overwrite parameter to replace the original file with the modified copy, like so

Replace-FileString  -Pattern 'r'  -Replacement ','  -Path Computers.txt  -Overwrite

Sample Application 2

Suppose that you have a client-server application called MyApplication. Numerous computers in the network use the client application to connect to the appserver1 server on TCP port 7840. Due to a security breach, the security administrator has dictated that the server portion of the application should now run on a different server (appserver2) and use a different port (8740). The client application stores the name of the server and TCP port in the C:Program FilesMy ApplicationMyApp.ini file. Figure 1 shows the relevant section of MyApp.ini for the computer named acct15.

You can't simply roll out an updated copy of the MyApp.ini file to the affected client machines because this file contains client-specific information (in this case, the computer name). Instead, you can use Replace-FileString.ps1 to update the .ini files on the affected computers.

First, you need to place the computer names that run the client application in a text file, one computer name per line, in a file called Clients.txt (see Figure 2).

Then, you can use the command in Listing 1 to modify the MyApp.ini files.

Listing 1: Command to Modify the MyApp.ini Files

Get-Content Clients.txt | ForEach-Object \{

  Get-Item "\$_C$Program FilesMy ApplicationMyApp.ini" \} |  Replace-FileString -Pattern 'Server=appserver1(r)Port=7840'  -Replacement 'Server=appserver2$1Port=8740' -Overwrite

In this command, the Get-Content cmdlet retrieves each computer name in Clients.txt. The ForEach-Object cmdlet retrieves the MyApp.ini file on each computer using the Get-Item cmdlet. Finally, the command uses the retrieved file object as input for the Replace-FileString.ps1 script. Using the pattern and replacement strings described in Table 3 along with the -Overwrite parameter, the script updates MyApp.ini with the changes. Because the .NET regular expression engine doesn't support escape sequences (such as r and ) in the replacement string, this command uses parentheses and $1 to insert the line break.

Sample Application 3

Suppose you downloaded a set of sample system management VBScript scripts from a website to C:SampleScripts on your computer. All the scripts contain the sample LDAP path DC=fabrikam,DC=com. Rather than edit the sample scripts one at a time, you can use Replace-FileString.ps1 to replace the sample LDAP path with your network's LDAP path. To do so, you just need to run the command

Replace-FileString  -Pattern 'DC=fabrikam,DC=com'  -Replacement 'your LDAP path'  -Path C:SampleScripts*.vbs  -Overwrite

where 'your LDAP path' is your network's LDAP path.

Easily Edit Files with Regular Expressions

PowerShell doesn't have a native cmdlet for replacing strings in files, but you can use Replace-FileString.ps1 to fill this void. This script makes it easy to replace strings in one or more files using regular expressions. You can download Replace-FileString.ps1 by clicking the Download the Code button at the top of page 1.

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like