← Back to Blog

Developers & Code | Jun 1, 2026 | 6 min read

How to Copy PowerShell Here-Strings Without Breakage

By Deepender Yadav

How to Copy PowerShell Here-Strings Without Breakage — Edge Drop Guide

PowerShell has two cmdlets for the clipboard: Set-Clipboard (write) and Get-Clipboard (read). They look simple. They are not. The two failure modes that catch developers are the trailing newline that Set-Clipboard adds to multi-line input, and the CRLF line endings that PowerShell uses on Windows but that other tools (bash, Python on Linux, JSON parsers in strict mode) do not expect. Neither failure mode is documented prominently. Both produce bugs that are hard to trace because the clipboard contents look correct until they are piped into something that cares about whitespace.

This guide covers PowerShell here-strings (the cleanest way to put a multi-line block on the clipboard) and the gotchas of Set-Clipboard and Get-Clipboard. It is written for developers using PowerShell on Windows 10 and 11. For neighbouring topics, see copying from Windows Terminal without garbled codes, JSON payloads: keep them as files, not clips, and developer copy-paste hygiene.

What a PowerShell here-string is

A here-string is a multi-line string literal in PowerShell. It starts with @" (or @') on its own line and ends with "@ (or '@) at the start of a line. Everything in between is the string content, including newlines, quotes, and special characters.

$block = @"
Line 1
Line 2 with "quotes"
Line 3 with `$(variable interpolation)
"@

Key points:

  • @" must be the last thing on its line. Nothing can follow it, not even a comment.
  • "@ must be the first thing on its line. No leading whitespace, no trailing characters.
  • @"..."@ is an expanding here-string. Variables and subexpressions are interpolated.
  • @'...'@ is a literal here-string. No interpolation; everything is taken literally.
  • The closing "@ is not included in the string. The string ends at the newline before the closing "@.

Here-strings are the cleanest way to put a multi-line block on the clipboard, because they preserve the line structure exactly and avoid the quoting issues that single-line string concatenation introduces.

Putting a here-string on the clipboard

The pattern is straightforward:

$snippet = @"
function Get-Greeting {
    param([string]$Name = "World")
    "Hello, $Name!"
}
"@
Set-Clipboard -Value $snippet

After running this, the snippet is on the clipboard. Pasting into VS Code, Slack, or a file produces the multi-line block correctly.

For a here-string that contains PowerShell variables that should be interpolated, use @"..."@. For a here-string that contains literal text (including PowerShell variable syntax that should not be interpolated), use @'...'@. The literal form is safer when the content is code in another language that uses $ for variables.

The trailing newline gotcha

Set-Clipboard adds a trailing newline to multi-line input in some PowerShell versions. The exact behaviour has shifted across versions and is not consistently documented. The symptom is that pasting into a text editor shows an extra blank line at the end, or piping to a command that counts lines returns one more line than expected.

To verify whether your PowerShell version adds the trailing newline:

"hello" | Set-Clipboard
(Get-Clipboard).Length  # Should be 5; if it's 6, a newline was added

If a trailing newline is being added and it matters for the target, strip it:

$snippet = $snippet -replace "\r?\n
quot; Set-Clipboard -Value $snippet

For most paste targets (chat, code editors, ticket descriptions), the trailing newline does not matter. For targets that parse the clipboard content (a JSON parser, a YAML parser, a hash calculator), it does.

The CRLF gotcha

PowerShell on Windows uses CRLF (\r\n) line endings for Set-Clipboard and Get-Clipboard. This is correct for Windows tools (Notepad, Word, Outlook) but causes failures when the clipboard content is piped into tools that expect LF (\n):

  • bash in WSL receives the CRLF and treats the \r as part of the last line. echo $(Get-Clipboard) in WSL with a multi-line clipboard will have stray \r characters that break parsing.
  • Python in WSL receives the CRLF and may include the \r in strings read from stdin.
  • JSON parsers in strict mode reject \r inside strings; the clipboard content fails to parse.
  • YAML parsers in strict mode may reject \r inside block scalars.

The fix is to convert CRLF to LF when reading from the clipboard in a context that expects Unix line endings:

# PowerShell: read clipboard, convert CRLF to LF
$clean = (Get-Clipboard) -replace "`r`n", "`n"
# bash: read Windows clipboard, strip \r
content=$(powershell.exe -Command Get-Clipboard | tr -d '\r')

The tr -d '\r' pattern is the standard idiom in WSL; see WSL and Windows clipboard: what crosses the boundary for more.

Reading the clipboard

Get-Clipboard reads the current clipboard content as a string. For multi-line content, the result is a single string with embedded newlines. For an array of lines, use -Split:

$lines = (Get-Clipboard) -Split "`r`n"

This splits on CRLF and returns an array of lines. For LF-only content (rare on Windows), split on ` "n" `` instead.

For raw clipboard content (including any formatting), Get-Clipboard -Raw returns the entire clipboard as a single string without splitting on newlines. This is useful when the content is a JSON or YAML blob that should be preserved exactly.

Set-Clipboard versus clip.exe

PowerShell has two ways to put text on the clipboard:

  • Set-Clipboard -Value $text — the PowerShell cmdlet. Adds the trailing newline in some versions; uses CRLF.
  • $text | clip.exe — pipes to the Windows clip.exe command. Does not add a trailing newline; uses CRLF.

The behaviour difference matters. For a single-line string, both produce the same result. For a multi-line string, Set-Clipboard may add a trailing newline and clip.exe may not. For a string that ends with a newline already, Set-Clipboard may add a second newline.

The practical rule: use Set-Clipboard for PowerShell-internal workflows (the cmdlet is more discoverable and pipeline-friendly); use clip.exe when the trailing newline matters and you want to control it explicitly.

Common patterns

Put a code snippet on the clipboard

$snippet = @'
function Get-Hash {
    param([string]$Path)
    Get-FileHash -Path $Path -Algorithm SHA256
}
'@
Set-Clipboard -Value $snippet

Read a JSON blob from the clipboard and pretty-print it

$json = Get-Clipboard
$obj = $json | ConvertFrom-Json
$obj | ConvertTo-Json -Depth 10 | Set-Clipboard

This is useful for reformatting minified JSON copied from a browser's network panel. See JSON payloads: keep them as files, not clips for the limits of this pattern.

Copy a file's contents to the clipboard

Get-Content -Path .\config.json -Raw | Set-Clipboard

For files larger than a few KB, prefer sending the file path rather than the contents. See how to copy a file path that works in the terminal for the path-copying pattern.

Copy command output to the clipboard

Get-Process | Select-Object -First 10 | Format-Table | Out-String | Set-Clipboard

The Out-String is necessary because Set-Clipboard expects a string, not a process object. Without Out-String, PowerShell stringifies the object using its default formatter, which may not match the table layout.

A note on cross-platform PowerShell

PowerShell 7 (the open-source, cross-platform version) runs on Linux and macOS as well as Windows. The clipboard cmdlets behave differently on non-Windows platforms:

  • Set-Clipboard and Get-Clipboard on Linux rely on xclip or xsel being installed. If neither is present, the cmdlets fail silently or throw an error depending on the version.
  • Set-Clipboard and Get-Clipboard on macOS rely on pbcopy and pbpaste, which are always present on macOS.
  • The CRLF line-ending gotcha does not apply on Linux and macOS, which use LF natively. Set-Clipboard on Linux writes LF; Get-Clipboard on Linux reads whatever is on the clipboard.

For developers using PowerShell 7 cross-platform, the practical rule is: test clipboard behaviour on each target platform, and do not assume Windows-specific behaviour. The here-string syntax is portable; the line-ending behaviour is not.

Common pitfalls summary

A short list of the pitfalls covered above, for quick reference:

  • @" must be the last thing on its line; "@ must be the first thing on its line. No exceptions.
  • Set-Clipboard may add a trailing newline. Strip it with -replace "\r?\n
    quot;
    if it matters for the target.
  • PowerShell on Windows uses CRLF. Convert to LF with -replace "\rn", "\n" for targets that expect Unix line endings.
  • Get-Clipboard returns a single string by default. Use -Split "\r\n" for an array of lines, or -Raw to preserve everything as one string.
  • Set-Clipboard expects a string. Pipe through Out-String first if the source is objects.
  • clip.exe is an alternative that does not add a trailing newline. Use it when the trailing newline matters.
  • Get-Clipboard on non-Windows platforms requires xclip/xsel (Linux) or pbcopy/pbpaste (macOS).

These seven pitfalls cover most of the failure modes developers encounter with PowerShell and the clipboard. Internalising them takes a few weeks of practice; forgetting them takes one bad paste.

Related reading

Sources

Deepender Yadav
Written by Deepender Yadav · Author & Developer

Deepender Yadav is a B.Tech Computer Science Engineering student and software developer interested in building practical software and open-source projects.

GitHub · LinkedIn

Copy. Stack. Drop.

Transform your clipboard into an interactive edge shelf. Stack, pin, and drag assets into any app with zero friction.

Download for Windows Get from Microsoft Store

How to Install Guide · First 10 Minutes Guide · Drag & Drop Guide · Edge-Drop vs Win+V · Support

Free · Lightweight · Privacy First
Find us on CodeHype