Skip to main content

A PowerShell version (not equivalent) of the GNU/Linux envsubst(1) utility.

# -----------------------------------------------------------------------
# Ignat said...
#
# There isn't a direct substitute for envsubst built into Windows, but you can
# achieve similar functionality with PowerShell. Here's a batch script you
# can use to replace environment variable references in the format ${VARIABLE_NAME} in a file:
# <https://superuser.com/a/1809135>
# ----------------------------------------------------------------------

Push-Location -Path '~/Downloads'

# Define some env vars:
$env:name = 'Jon'
$env:email = 'jon@example.net'
$env:missing = "i don't exist in template"

# Read the input/template file:
$content = Get-Content -Path 'test.tpl' -Raw;

# Find matches for environment variable references:
$matched = [Regex]::Matches($content, '\$\{([^}]+)\}');

# Interate over matches and performing replacement:
foreach ($match in $matched)
{
    $varName = $match.Groups[1].Value;
    $replacement = (Get-Item -LiteralPath "Env:$varName").Value;
    $content = $content.Replace($match.Value, $replacement);
}

# Write the modified content to the replaced output file:
Set-Content -Path 'output.txt' -Value $content

# Together, these parts create a script that can replace ${VARIABLE_NAME}
# patterns in a file with their corresponding environment variable values on a
# Windows machine using PowerShell.

# ------------------------------------------------------------
# Another, similar way (un-tested)
# ------------------------------------------------------------

<#
.SYNOPSIS
    Substitute environment variables, *similar* to envsubst(1).

.DESCRIPTION
    The envsubst program substitutes the values of environment variables.

.NOTES
    It does so using PowerShell variables, so if you want to use environment
    variables, you either have to name them like ${env:USERNAME} (or $Env:UserName)
    (which would be incompatible with envsubst), or you have to copy the environment
    variables into PowerShell variables first: `Get-ChildItem Env: | Set-Variable`

    The safe way to expand variables in a string in PowerShell is to use:
    `$ExecutionContext.InvokeCommand.ExpandString($String)`

.EXAMPLE
    cat template.yml | envsubst > result.yml

.LINK
    https://superuser.com/questions/1193131/what-is-the-windows-equivalent-for-envsubst-in-linux

.LINK
    https://www.gnu.org/software/gettext/manual/html_node/envsubst-Invocation.html
#>
function envsubst
{
    param(
        [Parameter(ValueFromPipeline)]
        [string] $InputObject
    )

    # Create a local PowerShell variable for each environment variable
    Get-ChildItem Env: | Set-Variable

    # The safe way to expand variables in a string in PowerShell
    $ExecutionContext.InvokeCommand.ExpandString($InputObject)
}