By Davy Rogers. Use these techniques only in environments you own or have explicit permission to test.

PowerShell: Working with Strings

String manipulation is essential for processing text, parsing output, and building commands dynamically. PowerShell provides powerful string operations for searching, replacing, splitting, joining, and formatting text. This lesson covers everything you need to master strings in PowerShell.

What You'll Learn

  • Creating and using strings
  • String concatenation and interpolation
  • String methods and operators
  • Searching and replacing text
  • Splitting and joining strings
  • Regular expressions in PowerShell
  • String formatting
  • Practical pentesting scenarios

Creating Strings

Single vs Double Quotes

# Single quotes (literal - no variable expansion)
$name = 'Alice'
Write-Host 'Hello, $name'
# Output: Hello, $name

# Double quotes (variable expansion)
$name = "Alice"
Write-Host "Hello, $name"
# Output: Hello, Alice

Here-Strings

# Single-quoted here-string (literal)
$text = @'
This is line 1
This is line 2
Variables like $name are not expanded
'@

# Double-quoted here-string (variable expansion)
$name = "Alice"
$text = @"
Hello, $name!
This allows multiple lines
and variable expansion
"@

String Concatenation

Using + Operator

# Concatenate strings
$first = "Hello"
$second = "World"
$result = $first + " " + $second
# Output: Hello World

# Concatenate with variables
$greeting = "Hello, " + $name + "!"

Using String Interpolation

# Much cleaner!
$name = "Alice"
$greeting = "Hello, $name!"

# With expressions
$x = 5
$y = 10
"The sum is: $($x + $y)"
# Output: The sum is: 15

Using -f Format Operator

# Format string
$name = "Alice"
$age = 25
"{0} is {1} years old" -f $name, $age
# Output: Alice is 25 years old

# With different order
"{1} is the age of {0}" -f $name, $age
# Output: 25 is the age of Alice

String Properties and Methods

Length Property

$text = "Hello, World!"
$text.Length
# Output: 13

Common String Methods

$text = "Hello, World!"

# Case conversion
$text.ToUpper()           # HELLO, WORLD!
$text.ToLower()           # hello, world!

# Trim whitespace
"  Hello  ".Trim()        # Hello
"  Hello  ".TrimStart()   # "Hello  "
"  Hello  ".TrimEnd()     # "  Hello"

# Substring
$text.Substring(0, 5)     # Hello
$text.Substring(7)        # World!

# Replace
$text.Replace("World", "PowerShell")  # Hello, PowerShell!

# Contains
$text.Contains("World")   # True

# StartsWith / EndsWith
$text.StartsWith("Hello") # True
$text.EndsWith("!")       # True

# Index of
$text.IndexOf("World")    # 7
$text.LastIndexOf("o")    # 8

# Pad
"Hi".PadLeft(5, '*')      # ***Hi
"Hi".PadRight(5, '*')     # Hi***

String Operators

-eq, -ne (Equality)

"hello" -eq "hello"       # True
"hello" -eq "Hello"       # True (case-insensitive by default)
"hello" -ceq "Hello"      # False (case-sensitive)

"hello" -ne "world"       # True (not equal)

-like, -notlike (Wildcards)

"PowerShell" -like "Power*"     # True
"PowerShell" -like "*Shell"     # True
"PowerShell" -like "*wer*"      # True

"PowerShell" -notlike "Bash*"   # True

# ? matches single character
"test" -like "t?st"             # True

-match, -notmatch (Regex)

"abc123" -match "\d+"           # True (contains digits)
"abc123" -match "^[a-z]+"       # True (starts with letters)

"[email protected]" -match "\w+@\w+\.\w+"  # True (email pattern)

"PowerShell" -notmatch "\d+"    # True (no digits)

-replace (Replace with Regex)

# Simple replace
"Hello World" -replace "World", "PowerShell"
# Output: Hello PowerShell

# Regex replace
"abc123def456" -replace "\d+", "NUM"
# Output: abcNUMdefNUM

# Remove all digits
"abc123def456" -replace "\d+", ""
# Output: abcdef

# Case-insensitive by default
"HELLO" -replace "hello", "Hi"
# Output: Hi

# Case-sensitive replace
"HELLO" -creplace "HELLO", "Hi"
# Output: Hi

Splitting Strings

Split Method

# Split by space
"one two three".Split(" ")
# Output: @("one", "two", "three")

# Split by multiple characters
"one,two;three".Split(",;")
# Output: @("one", "two", "three")

# Split and limit results
"a b c d e".Split(" ", 3)
# Output: @("a", "b", "c d e")

-split Operator

# Simple split
"one two three" -split " "
# Output: @("one", "two", "three")

# Regex split
"one123two456three" -split "\d+"
# Output: @("one", "two", "three")

# Split by newline
$text = @"
Line 1
Line 2
Line 3
"@
$text -split "`n"

# Limit results
"a b c d e" -split " ", 3
# Output: @("a", "b", "c d e")

Joining Strings

-join Operator

# Join array elements
$array = @("one", "two", "three")
$array -join " "
# Output: one two three

$array -join ", "
# Output: one, two, three

$array -join ""
# Output: onetwothree

Join Method

[string]::Join(", ", @("one", "two", "three"))
# Output: one, two, three

String Formatting

-f Format Operator

# Basic formatting
"{0} {1}" -f "Hello", "World"
# Output: Hello World

# Multiple uses of same argument
"{0} {0} {1}" -f "Hello", "World"
# Output: Hello Hello World

# Number formatting
"{0:N2}" -f 1234.5678
# Output: 1,234.57

# Currency
"{0:C}" -f 1234.56
# Output: $1,234.56

# Percentage
"{0:P}" -f 0.75
# Output: 75.00%

# Date formatting
"{0:yyyy-MM-dd}" -f (Get-Date)
# Output: 2025-10-08

# Padding
"{0,10}" -f "Hi"        # Right-align in 10 chars
"{0,-10}" -f "Hi"       # Left-align in 10 chars

Regular Expressions

Matching

# Check if string matches pattern
"test123" -match "\d+"
# Output: True

# Access matched text
$matches[0]
# Output: 123

# Named capture groups
"John Doe" -match "(?<first>\w+) (?<last>\w+)"
$matches.first  # John
$matches.last   # Doe

Select-String

# Search in files
Select-String -Path *.txt -Pattern "error"

# Search with regex
Select-String -Path *.log -Pattern "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"

# Get matched text only
Select-String -Path file.txt -Pattern "password" | Select-Object -ExpandProperty Line

# Case-sensitive search
Select-String -Path file.txt -Pattern "ERROR" -CaseSensitive

Practical Examples

Example 1: Extract IP Addresses

$text = "Server 192.168.1.1 is down. Try 10.0.0.5 instead."
$ipPattern = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
[regex]::Matches($text, $ipPattern) | ForEach-Object { $_.Value }
# Output: 192.168.1.1, 10.0.0.5

Example 2: Parse Log File

$logLine = "2025-10-08 14:30:15 ERROR Failed login from 192.168.1.100"
$parts = $logLine -split " ", 5
$date = $parts[0]
$time = $parts[1]
$level = $parts[2]
$message = $parts[3..4] -join " "

Write-Host "Date: $date"
Write-Host "Time: $time"
Write-Host "Level: $level"
Write-Host "Message: $message"

Example 3: Clean and Format Data

$names = @("  alice  ", "BOB", "  charlie")
$cleaned = $names | ForEach-Object {
    $_.Trim().Substring(0,1).ToUpper() + $_.Trim().Substring(1).ToLower()
}
# Output: Alice, Bob, Charlie

Example 4: Build SQL Query

$table = "Users"
$columns = @("Id", "Name", "Email")
$query = "SELECT {0} FROM {1}" -f ($columns -join ", "), $table
# Output: SELECT Id, Name, Email FROM Users

Example 5: Parse Command Output

# Get process info and extract PID
$output = "chrome.exe  12345  Console  1  150,000 K"
if ($output -match "(\d+)\s+Console") {
    $pid = $matches[1]
    Write-Host "Process ID: $pid"
}

Practical Pentesting Scenarios

Scenario 1: Extract Credentials from Text

$config = Get-Content config.txt -Raw
if ($config -match 'password["\s:=]+([^"\s]+)') {
    $password = $matches[1]
    Write-Host "Found password: $password"
}

Scenario 2: Parse Nmap Output

$nmapOutput = Get-Content nmap_results.txt
$openPorts = $nmapOutput | Where-Object { $_ -match "(\d+)/tcp\s+open" } | ForEach-Object {
    if ($_ -match "(\d+)/tcp") {
        $matches[1]
    }
}
Write-Host "Open ports: $($openPorts -join ', ')"

Scenario 3: Build Attack Command

$target = "192.168.1.100"
$username = "admin"
$passwordList = "passwords.txt"
$command = "hydra -l {0} -P {1} ssh://{2}" -f $username, $passwordList, $target
Write-Host $command

Scenario 4: Clean and Sort Subdomain List

$subdomains = Get-Content subdomains.txt
$cleaned = $subdomains | ForEach-Object {
    $_.Trim().ToLower()
} | Sort-Object -Unique
$cleaned | Out-File subdomains_cleaned.txt

Scenario 5: Extract Email Addresses

$html = Get-Content website.html -Raw
$emailPattern = '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
[regex]::Matches($html, $emailPattern) | ForEach-Object {
    $_.Value
} | Sort-Object -Unique

StringBuilder for Performance

Why StringBuilder?

# Slow (creates new string each time)
$result = ""
1..1000 | ForEach-Object {
    $result += "Line $_`n"
}

# Fast (modifies in place)
$sb = New-Object System.Text.StringBuilder
1..1000 | ForEach-Object {
    $sb.AppendLine("Line $_") | Out-Null
}
$result = $sb.ToString()

Escape Characters

Common Escapes

`n    # Newline
`r    # Carriage return
`t    # Tab
`0    # Null
``    # Backtick
`"    # Double quote
`'    # Single quote

Examples:

"Line 1`nLine 2"
# Output:
# Line 1
# Line 2

"Column1`tColumn2`tColumn3"
# Output: Column1    Column2    Column3

"He said, `"Hello!`""
# Output: He said, "Hello!"

Quick Reference

Creation:
$str = "text"
$str = 'literal'
$str = @"..."@  # Here-string

Concatenation:
"Hello " + "World"
"Hello $name"
"{0} {1}" -f "Hello", "World"

Methods:
$str.ToUpper()
$str.ToLower()
$str.Trim()
$str.Substring(start, length)
$str.Replace("old", "new")
$str.Split(" ")
$str.Contains("text")
$str.StartsWith("prefix")
$str.EndsWith("suffix")

Operators:
-eq, -ne        # Equal, not equal
-like           # Wildcard match
-match          # Regex match
-replace        # Regex replace
-split          # Split string
-join           # Join array

Regex:
"text" -match "pattern"
$matches[0]     # Matched text
Select-String -Path file.txt -Pattern "pattern"

Formatting:
"{0:N2}" -f 123.456      # Number
"{0:C}" -f 123.45        # Currency
"{0:P}" -f 0.75          # Percentage
"{0:yyyy-MM-dd}" -f (Get-Date)  # Date

Common Pitfalls

1. String Comparison Case Sensitivity

# Case-insensitive by default
"hello" -eq "HELLO"   # True

# Use -ceq for case-sensitive
"hello" -ceq "HELLO"  # False

2. Single vs Double Quotes

$name = "Alice"
'Hello, $name'   # Output: Hello, $name
"Hello, $name"   # Output: Hello, Alice

3. Forgetting Escape Characters

# Wrong: interpreted as variable
"C:\Users\$name\Desktop"

# Right: escape or use single quotes
"C:\Users\`$name\Desktop"
'C:\Users\$name\Desktop'

Resources

Help

Get-Help about_Operators
Get-Help about_Regular_Expressions
Get-Help about_Comparison_Operators

Online


Next Steps

  1. Practice regex with real data
  2. Master -replace for text processing
  3. Learn Select-String for file searching
  4. Use StringBuilder for performance
  5. Build dynamic commands with string formatting

String manipulation is fundamental to PowerShell. Master these techniques and you'll process text data like a pro!


"PowerShell strings: Where 'Hello, $name' actually says hello."