Variable filters

By default, bindings are inserted into the output as-is; no consideration is given as to whether the target variable or file is XML, HTML, JSON etc. That is, the target file type is always treated as plain text.

Octopus variable substitutions support filters to correctly encode values for a variety of target file types. These are invoked using the | (pipe) operator.

Given the variable:

NameValueScope
ProjectNameYou & I

And the template:

<h3>#{ProjectName | HtmlEscape}</h3>

The result will be:

<h3>You &amp; I</h3>

That is, the ampersand has been encoded correctly for use in an HTML document.

The filters provided by Octopus are for use with trusted input; don鈥檛 rely on them to sanitize data from potentially malicious sources.

Provided filters

Octopus provides a number of different types of filters for variable values:

Core filters

These core filters perform common string operations.

NamePurposeExample inputExample output
FormatApplies a format4.3$4.30
ReplaceReplaces a pattern1;2;31, 2, 3
ToLowerForces values to lowercaseAutomated Deploymentautomated deployment
ToUpperForces values to uppercaseAutomated DeploymentAUTOMATED DEPLOYMENT
TrimRemoves whitespace from the start/end路路路Bar路路路Bar
TruncateLimits the length of valuesOctopus DeployOctopus...
SubstringExtracts a range of characters by positionOctopus DeployDeploy

Format

The Format filter allows for converting of input based on an additionally provided argument that is passed to the .ToString() method.

MyVar ValueFilter ExpressionOutput
4.3#{MyVar | Format C}$4.30
2030/05/22 09:05:00#{MyVar | Format yyyy}2030
#{ | NowDate | Format Date MMM}Nov
#{Octopus.Deployment.Created}#{MyVar | Format "MM/dd/yyyy"}01/01/2020
#{Octopus.Deployment.Created}#{MyVar | Format "hh:mm:ss tt zz"}11:09:38 AM +01

Replace

The Replace filter performs a regular expression replace function on the variable. The regular expression should be provided in the .NET Framework format. Double quotes need to be used around any expressions that contain whitespace or special characters. Expressions containing double quotes can not be expressed inline, but can be done via nested variables. If both the search and replace expressions are variables, ensure there is no space between the expressions. For using Replace on special characters, you should escape the first parameter which will be the regex but the second parameter can be left as a string - see last example below.

MyVar ValueFilter ExpressionOutput
abc#{MyVar | Replace b}ac
abc#{MyVar | Replace b X}aXc
a b c#{MyVar | Replace "a b" X}X c
ab12c3#{MyVar | Replace "[0-9]+" X}abXcX
abc#{MyVar | Replace "(.)b(.)" "$2X$1" }cXa
abc#{MyVar | Replace #{match} #{replace}}a_c (when match=b and replace=_)
abc#{MyVar | Replace #{match} _}a_c (when match=b)
a\b#{MyVar | Replace "\\" "\\"}a\\b

Substring

The Substring filter extracts a range of characters from the input and outputs them. If two arguments are supplied, they are interpreted as start and end offsets of the range. If only one argument is supplied, it is interpreted as the end offset of a range starting at 0.

MyVar ValueFilter ExpressionOutput
Octopus Deploy#{MyVar | Substring 8 6}Deploy
Octopus Deploy#{MyVar | Substring 7}Octopus
Octopus Deploy#{MyVar | Substring 2 3}top

Trim

The Trim filter removes any whitespace from the ends of the input. Both ends are trimmed unless an optional argument of start or end is provided.

MyVar ValueFilter ExpressionOutput
路路路Bar路路路#{MyVar | Trim}Bar
路路路Bar路路路#{MyVar | Trim start}Bar路路路
路路路Bar路路路#{MyVar | Trim end}路路路Bar

Truncate

The Truncate filter limits the length of the input. If the input is longer than the length specified by the argument, the rest is replaced with an ellipsis.

MyVar ValueFilter ExpressionOutput
Octopus Deploy#{MyVar | Truncate 7}Octopus...
abc#{MyVar | Truncate 7}abc

Comparison filters

These filters return true or false depending on the result of a comparison. They are typically useful for specifying the condition in an #{if} block.

Note: Entries marked with * are supported from the version of Octopus listed.

NamePurposeExample inputExample output
Contains
*2021.2.0
Determines whether a string contains a given stringOctopus Deptrue
EndsWith
*2021.2.0
Determines whether the end of a string matches a given stringDeploytrue
Match
*2021.2.0
Determines whether a string contains a given regular expression pattern"Octo.*Deploy"true
StartsWith
*2021.2.0
Determines whether the beginning of a string matches a given stringOctotrue

Match

The Match filter searches the input for an occurrence of a given regular expression pattern. It returns true if an occurrence is found, and false otherwise. The regular expression should be provided in the .NET Framework format. Double quotes need to be used around any expressions that contain whitespace or special characters. Expressions containing double quotes can not be expressed inline, but can be done via nested variables.

MyVar ValueFilter ExpressionOutput
abc#{MyVar | Match abc}true
abc#{MyVar | Match def}false
a b c#{MyVar | Match "a b"}true
ab12c3#{MyVar | Match "ab[0-9]+"}true
abc#{MyVar | Match #{pattern}}true (when match=abc)

StartsWith, EndsWith and Contains

The StartsWith, EndsWith and Contains filters compare the input to a given string argument. They return true if the argument matches, and false otherwise. The comparison is case-sensitive. Strings are compared as Ordinals. Double quotes need to be used around any expressions that contain whitespace or special characters. Expressions containing double quotes can not be expressed inline, but can be done via nested variables.

MyVar ValueFilter ExpressionOutput
abc#{MyVar | StartsWith ab}true
abc#{MyVar | StartsWith bc}false
abc#{MyVar | StartsWith Ab}false
abc#{MyVar | EndsWith bc}true
abc#{MyVar | EndsWith ab}false
abc#{MyVar | EndsWith bC}false
abc#{MyVar | Contains bc}true
abc#{MyVar | Contains ab}true
abc#{MyVar | Contains AbC}false
a b(c#{MyVar | Contains " b("}true
a"b"c#{MyVar | Contains #{str}}true (when str="b")

Conversion filters

These filters provide a mechanism to convert a value from one form to another.

NamePurposeExample inputExample output
FromBase64Converts values from Base64 (using UTF encoding)QmF6Bar
ToBase64Converts values to Base64 (using UTF encoding)BarQmF6
MarkdownToHTMLConverts Markdown to HTMLThis \_rocks\_\<p>This \<em>rocks\</em>\</p>

Date filters

These filters are used to work with dates.

NamePurposeExample inputExample output
NowDateOutputs the current date2016-11-03T08:53:11.0946448
NowDateUtcOutputs the current date in UTC2016-11-02T23:01:46.9441479Z

NowDate and NowDateUtc

The NowDate and NowDateUtc filters take no variable input but can take an additional optional right-hand-side argument the define the string format (Defaults to ISO-8601 Round-trip format).

MyFormat VariableFilter ExpressionOutput
#{ | NowDate }2016-11-03T08:53:11.0946448
#{ | NowDateUtc}2016-11-02T23:01:46.9441479Z
#{ | NowDate "HH dd-MMM-yyyy"}09 03-Nov-2016
#{ | NowDateUtc zz}+00
dd-MM-yyyy#{ | NowDate #{MyFormat}}03-Nov-2016

Escaping filters

These filters apply format-specific escaping rules.

Note: Entries marked with * are supported from the version of Octopus listed.

NamePurposeExample inputExample output
HtmlEscapeEscapes entities for use in HTML content1 < 21 \&lt; 2
JsonEscapeEscapes data for use in JSON stringsHe said "Hello!"He said \\"Hello!\\"
PropertiesKeyEscape
*2020.4.0
Escapes data for use in .properties keysHey: x=yHey\:\ x\=y
PropertiesValueEscape
*2020.4.0
Escapes data for use in .properties valuesa\b=ca\\b=c
UriEscapeEscape a URI stringA b:c+d/eA%20b:c+d/e
UriDataEscapeEscape a URI data stringA b:c+d/eA%20b%3Ac%2Bd%2Fe
XmlEscapeEscapes entities for use in XML content1 < 21 \&lt; 2
YamlDoubleQuoteEscape
*2020.4.0
Escapes data for use in YAML double quoted strings"Hello"\Goodbye\"Hello\"\\Goodbye
YamlSingleQuoteEscape
*2020.4.0
Escapes data for use in YAML single quoted stringsThe bee's kneesThe bee''s knees

Extraction filters

These filters extract a part of value.

Note: Entries marked with * are supported from the version of Octopus listed.

NamePurposeExample inputExample output
UriPartExtracts a specified part of a URI stringhttps://octopus.com/docs/docs
VersionMajor
*2020.5.0
Extracts the major version field from a version string1.2.3.4-my-branch.1.2+build101
VersionMinor
*2020.5.0
Extracts the minor version field from a version string1.2.3.4-my-branch.1.2+build102
VersionPatch
*2020.5.0
Extracts the patch version field from a version string1.2.3.4-my-branch.1.2+build103
VersionRevision
*2020.5.0
Extracts the revision version field from a version string1.2.3.4-my-branch.1.2+build104
VersionPreRelease
*2020.5.0
Extracts the prerelease field from a version string1.2.3.4-my-branch.1.2+build10my-branch.1.2
VersionPreReleasePrefix
*2020.5.0
Extracts the prefix from the prerelease field from a version string1.2.3.4-my-branch.1.2+build10my-branch
VersionPreReleaseCounter
*2020.5.0
Extracts the counter from the prerelease field from a version string1.2.3.4-my-branch.1.2+build101.2
VersionMetadata
*2020.5.0
Extracts the metadata field from a version string1.2.3.4-my-branch.1.2+build10build10

UriPart

The UriPart filter parses the input as a URI and extracts a specified part of it. A helpful error will be written to the output if there is an error in the input or the filter expression.

MyVar ValueFilter ExpressionOutput
https://octopus.com/docs#{MyVar | UriPart AbsolutePath}/docs
https://octopus.com/docs#{MyVar | UriPart AbsoluteUri}https://octopus.com/docs
https://octopus.com/docs#{MyVar | UriPart Authority}octopus.com
https://octopus.com/docs#{MyVar | UriPart DnsSafeHost}octopus.com
https://octopus.com/docs#filters#{MyVar | UriPart Fragment}#filters
https://octopus.com/docs#{MyVar | UriPart Host}octopus.com
https://octopus.com/docs#{MyVar | UriPart HostAndPort}octopus.com:443
https://octopus.com/docs#{MyVar | UriPart HostNameType}Dns
https://octopus.com/docs#{MyVar | UriPart IsAbsoluteUri}true
https://octopus.com/docs#{MyVar | UriPart IsDefaultPort}true
https://octopus.com/docs#{MyVar | UriPart IsFile}false
https://octopus.com/docs#{MyVar | UriPart IsLoopback}false
https://octopus.com/docs#{MyVar | UriPart IsUnc}false
https://octopus.com/docs#{MyVar | UriPart Path}/docs
https://octopus.com/docs?filter=faq#{MyVar | UriPart PathAndQuery}/docs?filter=faq
https://octopus.com/docs#{MyVar | UriPart Port}443
https://octopus.com/docs?filter=faq#{MyVar | UriPart Query}?filter=faq
https://octopus.com/docs#{MyVar | UriPart Scheme}https
https://octopus.com/docs#{MyVar | UriPart SchemeAndServer}https://octopus.com
https://username:password@octopus.com#{MyVar | UriPart UserInfo}username:password

Differences from regular variable bindings

Because of the flexibility provided by the extended syntax, variables that are not defined will result in the source text, e.g. #{UndefinedVar} being echoed rather than an empty string, so that evaluation problems are easier to spot and debug. The if construct can be used to selectively bind to a variable only when it is defined, e.g. to obtain identical 鈥渆mpty鈥 variable functionality as shown in the first example:

Server=#{if DatabaseServer}#{DatabaseServer}#{/if};

JSON parsing

Octostache 2.x includes an update to support parsing JSON formatted variables natively, and using their contained properties for variable substitution.

Given the variable:

NameValueScope
Custom.MyJson{Name: "t-shirt", Description: "I am a shirt", Sizes: [{size: "small", price: 15.00}, {size: "large", price: 20.00}]}
Custom.MyJson.DescriptionShirts are not shorts.

And the template:

<h1>#{Custom.MyJson[Name]}</h1>
#{Custom.MyJson.Name} - #{Custom.MyJson.Description}
From: #{Custom.MyJson.Sizes[0].price | Format C}
Sizes: #{Custom.MyJson.Sizes}

The result will be:

<h1>t-shirt</h1>
t-shirt - Shirts are not shorts
From: $15.00
Sizes: [{size: "small", price: 15.00}, {size: "large", price: 20.00}]

There are a few things to note here:

  • The Name property is extracted from the JSON using either dot-notation or indexing.
  • Providing an explicit project variable overrides one obtained by walking through the JSON.
  • Arrays can be accessed using standard numerical index notation.
  • Variables can map to a sub-section of the JSON variable.

Repetition over json

Given the variables:

NameValue
MyNumbers[5,2,4]
MyObjects{Cat: {Price: 11.5, Description: "Meow"}, Dog: {Price: 17.5, Description: "Woof"}}

And the template:

Numbers:
#{each number in MyNumbers}
 - #{number}
#{/each}

Objects:
#{each item in MyObjects}
	#{item.Key}: #{item.Value.Price}
#{/each} 

The resulting text will be:

Numbers:
 - 5
 - 2
 - 4
 
Objects:
Cat: 11.5
Dog: 17.5

Learn more

Help us continuously improve

Please let us know if you have any feedback about this page.

Send feedback

Page updated on Sunday, January 1, 2023