内置字符串

Page Contents

这些内置函数作用于字符串的左值。但是,如果左值是数字或日期/时间/日期时间或布尔值(从 2.3.20 开始),它将根据当前的数字,日期/时间/日期时间和布尔格式自动转换为字符串设置(与使用${...}插入此类值时所应用的格式程序相同)。

boolean

字符串转换为布尔值。该字符串必须为truefalse(区分大小写!),或必须采用boolean_format设置指定的格式。

如果字符串格式不正确,则当您尝试访问此内置文件时,将出错并中止模板处理。

cap_first

字符串首个单词大写的字符串。有关“单词”的确切含义,请参见word_list built-in。例:

${"  green mouse"?cap_first}
${"GreEN mouse"?cap_first}
${"- green mouse"?cap_first}

The output:

Green mouse
GreEN mouse
- green mouse

"- green mouse"的情况下,第一个单词是-

capitalize

所有单词都大写的字符串。有关“单词”的确切含义,请参见word_list built-in。例:

${"  green  mouse"?capitalize}
${"GreEN mouse"?capitalize}

The output:

Green Mouse
Green Mouse

chop_linebreak

如果有换行符,则在结尾处没有line-break的字符串,否则为未更改的字符串。

contains

Note:

从 FreeMarker 2.3.1 开始可以使用此内置功能。它在 2.3 中不存在。

返回子字符串是否指定为字符串中此内置事件的参数。例如:

<#if "piceous"?contains("ice")>It contains "ice"</#if>

这将输出:

It contains "ice"

日期,时间,日期时间

字符串值转换为日期,时间或日期时间值。它将期望由date_format,time_format 和 datetime_format 设置指定的格式。如果字符串格式不正确,则当您尝试访问此内置文件时,将出错并中止模板处理。

<#-- The date_format, time_format and datetime_format settings must match this format! -->
<#assign someDate = "Oct 25, 1995"?date>
<#assign someTime = "3:05:30 PM"?time>
<#assign someDatetime = "Oct 25, 1995 03:05:00 PM"?datetime>

<#-- Changing the setting value changes the expected format: -->
<#setting datetime_format="iso">
<#assign someDatetime = "1995-10-25T15:05"?datetime>

您还可以显式指定格式,例如?datetime.format(因此也可以指定为?datetime["format"])或?datetime("format");这三种形式都一样。也可以使用?date?time类似地指定格式。有关格式值的语法和含义,请参见date_format,time_format 和 datetime_format 设置的可能值。例:

<#-- Parsing XML Schema xs:date, xs:time and xs:dateTime values: -->
<#assign someDate = "1995-10-25"?date.xs>
<#assign someTime = "15:05:30"?time.xs>
<#assign someDatetime = "1995-10-25T15:05:00"?datetime.xs>

<#-- Parsing ISO 8601 (both extended and basic formats): -->
<#assign someDatetime = "1995-10-25T15:05"?datetime.iso>
<#assign someDatetime = "19951025T1505"?datetime.iso>

<#-- Parsing with SimpleDateFormat patterns: -->
<#assign someDate = "10/25/1995"?date("MM/dd/yyyy")>
<#assign someTime = "15:05:30"?time("HH:mm:ss")>
<#assign someDatetime = "1995-10-25 03:05 PM"?datetime("yyyy-MM-dd hh:mm a")>

<#-- Parsing with custom date formats: -->
<#assign someDatetime = "October/25/1995 03:05 PM"?datetime.@worklog>

为避免误解,左侧值不必为字符串 Literals。例如,当您从 XML DOM 读取数据时(所有值都是未解析的字符串),您可以执行order.confirmDate?date.xs之类的操作来将字符串值转换为实际日期。

当然,格式也可以是变量,例如"..."?datetime(myFormat)

请注意,从 2.3.24 版本开始,也可以使用 0 个参数(例如?date())来调用这些内置函数。它几乎与只写?date相同。区别是高度技术性的,几乎无关紧要:?date()和此类返回与日期解析器(freemarker.core.TemplateDateFormat实现)返回的 Java 对象完全相同,而没有()?date返回一个棘手的包装值,该值是日期,并且方法和哈希同时。

ends_with

返回此字符串是否以参数中指定的子字符串结尾。例如"ahead"?ends_with("head")返回布尔值true。同样,"head"?ends_with("head")将返回true

ensure_ends_with

Note:

从 FreeMarker 2.3.21 开始,此内置功能可用。

如果字符串不以指定为第一参数的子字符串结尾,则将其添加到字符串之后,否则返回原始字符串。例如,"foo"?ensure_ends_with("/")"foo/"?ensure_ends_with("/")都返回"foo/"

ensure_starts_with

Note:

从 FreeMarker 2.3.21 开始,此内置功能可用。

如果字符串不是以指定为第一个参数的子字符串开头,则将其添加到字符串之前,否则返回原始字符串。例如,"foo"?ensure_starts_with("/")"/foo"?ensure_starts_with("/")都返回"/foo"

如果指定两个参数,则将第一个参数解释为 Java 正则表达式,如果它与字符串的开头不匹配,则将指定为第二个参数的字符串添加到字符串之前。例如someURL?ensure_starts_with("[a-zA-Z]+://", "http://")将检查字符串是否以与"[a-zA-Z]+://"匹配的东西开头(请注意,不需要^),如果不需要,则在"http://"之前加上前缀。

此方法还接受第三个flags parameter。由于使用 2 个参数进行调用意味着在其中"r"(即正则表达式模式),因此您很少需要此参数。一种值得注意的情况是,当您不希望将第一个参数解释为正则表达式时,仅将其解释为纯文本,而又希望比较不区分大小写,在这种情况下,您应使用"i"作为第三个参数。

esc

Note:

从 FreeMarker 2.3.24 开始,此内置功能可用。

使用当前的output format来转义该值,并防止返回值auto-escaping(以避免两次转义)。由于具有自动转义功能,因此通常仅在禁用自动转义功能时才需要此功能:

<#ftl output_format="HTML" auto_esc=false>
<#assign s = "R&D">
${s}
${s?esc}
R&D
R&amp;D

在启用自动转义的模板中,使用它是多余的:

<#ftl output_format="HTML">
<#assign s = "R&D">
${s}
${s?esc} <#-- ?esc is redundant here -->
R&amp;D
R&amp;D

通过将字符串值转换为标记输出值,使用当前输出格式转义字符串并将结果用作标记,该内置函数起作用。最终的标记输出值在调用时属于当前输出格式。

只要 Importing 的标记输出值属于当前输出格式,此内置函数也可以应用于标记输出值,它将跳过而不会更改。如果不是这样,则必须将标记转换为当前的输出格式,当前(从 2.3.24 版本开始)只有在通过转义纯文本(通常使用?esc)创建该值时才会成功。

当前输出格式为非标记输出格式时,不能使用此内置函数。尝试这样做将导致parse-time error

此内置与已弃用的转义和无意指令无关。实际上,解析器将阻止在同一位置使用它们,以防止混淆。

groups

仅与内置matches的结果一起使用。见there...

html (deprecated)

Note:

2.3.24 中引入的auto-escaping mechanism不推荐使用此内置函数。通常,为了防止双重转义和混乱,在启用自动转义的地方使用此内置符号是parse-time error。为了帮助迁移,此内置插件无提示地绕过 HTML 标记输出值而不更改它们。

字符串作为 HTML 标记。也就是说,所有字符串:

  • <替换为&lt;

  • >替换为&gt;

  • &替换为&amp;

  • "替换为&quot;

  • '&#39;替换如果程序员具有设置 incompatible_improvements 设置到 2.3.24 或更高版本(也将其设置为 2.3.20 或更高并且您不在字符串 Literals 范围内)。否则'不会被替换,因此您必须使用引号("而不是')引用要安全插入值的属性值。

<input type=text name=user value="${user?html}">

Warning!

插入属性值时,请始终引用该属性,否则攻击者可能会利用它!这是错误的:<input name="user" value=${user?xhtml}>。很好:<input name="user" value="${user?xhtml}">

请注意,在 HTML 页面中,通常要对所有插值使用此内置函数。您可以使用escape directive节省大量键入时间,并减少意外错误的可能性。

index_of

返回指定子字符串首次出现在该字符串中的索引。例如,"abcabc"?index_of("bc")将返回 1(不要忘记第一个字符的索引为 0)。另外,您可以指定从以下位置开始搜索的索引:"abcabc"?index_of("bc", 2)将返回 4.第二个参数的数值没有限制:如果为负数,则其效果与零相同,并且为零。大于此字符串的长度,则具有与等于此字符串的长度相同的效果。十进制值将被截断为整数。

如果第一个参数未在该字符串中作为子字符串出现(如果使用第二个参数,则从给定索引开始),则它返回-1.

j_string

使用 Java 语言字符串 Literals 的转义规则对字符串进行转义,因此将值插入字符串 Literals 中是安全的。请注意,它将在插入值周围添加引号;您打算在字符串 Literals 中使用此* inside *。

UCS代码点 0x20 下的所有字符都将被转义。如果它们在 Java 语言中没有专用的转义序列(例如\n\t等),则将它们替换为 UNICODE 转义(\uXXXX)。

Example:

<#assign beanName = 'The "foo" bean.'>
String BEAN_NAME = "${beanName?j_string}";

will output:

String BEAN_NAME = "The \"foo\" bean.";

js_string

使用 JavaScript 语言字符串 Literals 的转义规则对字符串进行转义,因此将值插入字符串 Literals 中是安全的。请注意,它将在插入值周围添加引号;您打算在字符串 Literals 中使用此* inside *。

Warning!

当插入 HTML 属性中的 JavaScript 字符串 Literals 时,还必须使用 HTML 转义符对值进行转义。因此,您中没有自动 HTML 转义,这是 WRONG:<p onclick="alert('${message?js_string}')">,这很不错:<p onclick="alert('${message?js_string?html}')">

Example:

<#assign user = "Big Joe's \"right hand\"">
<script>
  alert("Welcome ${user?js_string}!");
</script>

will output:

<script>
  alert("Welcome Big Joe\'s \"right hand\"!");
</script>

确切的转义规则是:

  • "\"的形式转义

  • '\'的形式转义

  • \\\的形式转义

  • 如果/在转义字符串中<的正后方,或者在转义字符串的开头,则/被转义为\/

  • 如果>直接位于转义字符串中]]--的后面,或者它位于转义字符串的开头,或者如果在转义字符串的开头仅存在]-,则>被转义为\>

  • <如果在转义字符串中紧跟着?!,或者在转义字符串的末尾,则以\u003C进行转义

  • UCS代码点范围 U 0000 ... U 001f 和 U 007f ... U 009f 中的控制字符转义为\r\n等,或者转为\xXX,在 JavaScript 中没有特殊转义。

  • 具有UCS代码点 U 2028(行分隔符)和 U 2029(段落分隔符)的控制字符将作为\uXXXX进行转义,因为它们是 ECMAScript 中的源代码换行符。

json_string

使用 JSON 语言字符串 Literals 的转义规则对字符串进行转义,因此将值插入字符串 Literals 中是安全的。请注意,它将在插入值周围添加引号;您打算在字符串 Literals 中使用此* inside *。

这不会转义'个字符,因为 JSON 字符串必须用"引起来。

转义规则与记录为 js_string几乎相同。不同之处在于,根本不对'进行转义,对>进行转义为\ u003E(而不作为>),并且使用\uXXXX转义代替了\xXX转义。

keep_after

Note:

从 FreeMarker 2.3.21 开始,此内置功能可用。

删除第一次出现给定子字符串之后的字符串部分。例如:

${"abcdefgh"?keep_after("de")}

will print

fgh

如果找不到参数字符串,它将返回一个空字符串。如果参数字符串是长度为 0 的字符串,它将返回原始字符串不变。

此方法接受可选的flags parameter作为其第二个参数:

${"foo : bar"?keep_after(r"\s*:\s*", "r")}

will print

bar

keep_after_last

Note:

从 FreeMarker 2.3.22 开始,此内置功能可用。

keep_after相同,但保留 Component 在参数的最后一次出现之后,而不是在第一次出现之后。例:

${"foo.bar.txt"?keep_after_last(".")}

will print

txt

而使用keep_after,您将获得bar.txt

keep_before

Note:

从 FreeMarker 2.3.21 开始,此内置功能可用。

删除以给定子字符串开头的字符串部分。例如:

${"abcdef"?keep_before("de")}

will print

abc

如果没有找到参数字符串,它将返回原始字符串不变。如果参数字符串是长度为 0 的字符串,它将返回一个空字符串。

此方法接受可选的flags parameter作为其第二个参数:

${"foo : bar"?keep_before(r"\s*:\s*", "r")}

will print

foo

keep_before_last

Note:

从 FreeMarker 2.3.22 开始,此内置功能可用。

keep_before相同,但是将 Component 保留在最后一次出现参数之前,而不是在第一次出现之后。例:

${"foo.bar.txt"?keep_before_last(".")}

will print

foo.bar

而使用keep_before,您将获得foo

last_index_of

返回指定子字符串的最后一个(最右边)出现在此字符串内的索引。它返回子字符串的第一个(最左边)字符的索引。例如:"abcabc"?last_index_of("ab")将返回 3.此外,您可以指定索引以开始搜索。例如,"abcabc"?last_index_of("ab", 2)将返回 0.请注意,第二个参数指示子字符串开头的最大索引。第二个参数的数值没有限制:如果为负数,则具有与零相同的效果;如果它大于此字符串的长度,则与具有第二个参数的效果相同。等于此字符串的长度。十进制值将被截断为 inegers。

如果第一个参数未在该字符串中作为子字符串出现(在给定索引之前,如果使用第二个参数),则它返回-1.

left_pad

Note:

从 FreeMarker 2.3.1 开始可以使用此内置功能。

如果它与 1 个参数一起使用,则它将在字符串的开头插入空格,直到达到指定为参数的长度为止。如果字符串已经等于或大于指定的长度,则它将不执行任何操作。例如,这:

[${""?left_pad(5)}]
[${"a"?left_pad(5)}]
[${"ab"?left_pad(5)}]
[${"abc"?left_pad(5)}]
[${"abcd"?left_pad(5)}]
[${"abcde"?left_pad(5)}]
[${"abcdef"?left_pad(5)}]
[${"abcdefg"?left_pad(5)}]
[${"abcdefgh"?left_pad(5)}]

将输出以下内容:

[     ]
[    a]
[   ab]
[  abc]
[ abcd]
[abcde]
[abcdef]
[abcdefg]
[abcdefgh]

如果它与 2 个参数一起使用,则第一个参数的含义与您仅使用带有 1 个参数的内置参数的含义相同,而第二个参数则指定要插入的内容而不是空格字符。例如:

[${""?left_pad(5, "-")}]
[${"a"?left_pad(5, "-")}]
[${"ab"?left_pad(5, "-")}]
[${"abc"?left_pad(5, "-")}]
[${"abcd"?left_pad(5, "-")}]
[${"abcde"?left_pad(5, "-")}]

将输出以下内容:

[-----]
[----a]
[---ab]
[--abc]
[-abcd]
[abcde]

第二个参数可以是长度大于 1 的字符串。然后将定期插入该字符串,例如:

[${""?left_pad(8, ".oO")}]
[${"a"?left_pad(8, ".oO")}]
[${"ab"?left_pad(8, ".oO")}]
[${"abc"?left_pad(8, ".oO")}]
[${"abcd"?left_pad(8, ".oO")}]

将输出以下内容:

[.oO.oO.o]
[.oO.oO.a]
[.oO.oOab]
[.oO.oabc]
[.oO.abcd]

第二个参数必须是字符串值,并且必须至少包含 1 个字符。

length

字符串中的字符数。

lower_case

字符串的小写版本。例如"GrEeN MoUsE"?lower_case将是"green mouse"

matches

这是内置的“超级用户”。如果您不知道regular expressions,请忽略它。

此内置函数确定字符串是否与模式完全匹配。同样,它返回匹配子字符串的列表。返回值是一个多类型值:

  • 布尔值:true,如果整个字符串与模式匹配,则为false。例如,"fooo"?matches('fo*')true,但是"fooo bar"?matches('fo*')false

  • 序列:字符串的匹配子字符串列表。长度序列可能为 0.

For example:

<#if "fxo"?matches("f.?o")>Matches.<#else>Does not match.</#if>

<#assign res = "foo bar fyo"?matches("f.?o")>
<#if res>Matches.<#else>Does not match.</#if>
Matching sub-strings:
<#list res as m>
- ${m}
</#list>

will print:

Matches.

Does not match.
Matching sub-strings:
- foo
- fyo

如果正则表达式包含组(括号),则可以使用内置的groups来访问它们:

<#-- Entire input match -->
<#assign res = "John Doe"?matches(r"(\w+) (\w+)")>
<#if res> <#-- Must not try to access groups if there was no match! -->
  First name: ${res?groups[1]}
  Second name: ${res?groups[2]}
</#if>

<#-- Subtring matches -->
<#assign res = "aa/rx; ab/r;"?matches("(.+?)/*(.+?);")>
<#list res as m>
  - "${m}" is "${m?groups[1]}" per "${m?groups[2]}"
</#list>

这将打印:

First name: John
  Second name: Doe

  - "aa/rx;" is "a" per "a/rx"
  - " ab/r;" is " " per "ab/r"

有关groups内置行为的注意事项:

  • 它既适用于子字符串匹配,也适用于整个字符串匹配的结果(如上例所示)

  • groups返回的序列中的第一项是正则表达式匹配的整个子字符串。因此,第一个显式正则表达式组的索引(换句话说,正则表达式中第一个(...)的索引)为 1,而不是 0.而且,因此,序列的大小比的数目大一个。显式正则表达式组。

  • groups返回的序列的大小仅取决于正则表达式中显式组的数量,因此即使未找到正则表达式也将相同(非 0)。匹配时尝试访问序列中的某个项目(如res?groups[1])将导致错误。因此,在访问组之前,应始终检查是否存在任何匹配项(如<#if res>access the groups here</#if>)。

  • 如果正则表达式匹配,但正则表达式中的某个显式组不匹配,则该序列的序列将包含一个长度为 0 的字符串。因此,只要包含的正则表达式已匹配某些内容,访问不匹配的组是安全的。

matches接受可选的第二个参数flags。请注意,它不支持标志f,并且会忽略r标志。

no_esc

Note:

从 FreeMarker 2.3.24 开始,此内置功能可用。

防止值的auto-escaping。例如:

<#ftl output_format="HTML">
<#assign s = "<b>Test</b>">
${s}
${s?no_esc}
&lt;b&gt;Test&lt;/b&gt;
<b>Test</b>

这是通过将字符串值转换为标记输出值来实现的,该字符串原样使用该字符串作为标记,并且在调用时属于当前output format

只要 Importing 标记输出值属于当前输出格式,此内置函数也可以应用于标记输出值,它会绕过而不会更改。如果不是这样,则必须将标记转换为当前的输出格式,当前(从 2.3.24 版本开始)只有在通过转义纯文本(通常使用?esc)创建该值时才会成功。

当前输出格式为非标记输出格式时,不能使用此内置函数。尝试这样做将导致parse-time error

此内置与已弃用的转义和无意指令无关。实际上,解析器将阻止在同一位置使用它们,以防止混淆。

number

字符串转换为数值。该数字必须为“计算机语言”格式。也就是说,它必须采用与语言环境无关的形式,其中小数点分隔符是点,并且没有分组。

该内置功能可识别 FreeMarker 模板语言使用的格式的数字。另外,它识别科学计数法(例如"1.23E6""1.5e-8")。从 FreeMarker 2.3.21 开始,它还可以识别所有 XML Schema 数字格式,例如NaNINF-INF以及 Java 本地格式Infinity-Infinity

如果字符串格式不正确,则当您尝试访问此内置文件时,将出错并中止模板处理。

实际上,该字符串是通过当前arithmetic_enginetoNumber方法(配置设置)进行解析的。但是,该方法的行为应与上述类似。

replace

它用于将原始字符串中所有出现的字符串替换为另一个字符串。它不处理单词边界。例如:

${"this is a car acarus"?replace("car", "bulldozer")}

will print:

this is a bulldozer abulldozerus

替换按从左到右的 Sequences 进行。这意味着:

${"aaaaa"?replace("aaa", "X")}

will print:

Xaa

如果第一个参数是一个空字符串,则所有出现的空字符串都将被替换,就像"foo"?replace("","|")的值等于"|f|o|o|"

replace接受可选的flags parameter作为其第三个参数。

right_pad

Note:

从 FreeMarker 2.3.1 开始可以使用此内置功能。它在 2.3 中不存在。

这与left_pad相同,但是它将字符插入到字符串的末尾而不是字符串的开头。

Example:

[${""?right_pad(5)}]
[${"a"?right_pad(5)}]
[${"ab"?right_pad(5)}]
[${"abc"?right_pad(5)}]
[${"abcd"?right_pad(5)}]
[${"abcde"?right_pad(5)}]
[${"abcdef"?right_pad(5)}]
[${"abcdefg"?right_pad(5)}]
[${"abcdefgh"?right_pad(5)}]

[${""?right_pad(8, ".oO")}]
[${"a"?right_pad(8, ".oO")}]
[${"ab"?right_pad(8, ".oO")}]
[${"abc"?right_pad(8, ".oO")}]
[${"abcd"?right_pad(8, ".oO")}]

这将输出以下内容:

[     ]
[a    ]
[ab   ]
[abc  ]
[abcd ]
[abcde]
[abcdef]
[abcdefg]
[abcdefgh]

[.oO.oO.o]
[aoO.oO.o]
[abO.oO.o]
[abc.oO.o]
[abcdoO.o]

remove_beginning

Note:

从 FreeMarker 2.3.21 开始,此内置功能可用。

从字符串的开头删除参数子字符串,或者如果原始字符串不是以参数子字符串开头的,则返回原始字符串。例如:

${"abcdef"?remove_beginning("abc")}
${"foobar"?remove_beginning("abc")}

will print:

def
foobar

remove_ending

Note:

从 FreeMarker 2.3.21 开始,此内置功能可用。

从字符串的结尾删除参数子字符串,或者如果原始字符串不以参数子字符串结尾,则返回原始字符串。例如:

${"abcdef"?remove_ending("def")}
${"foobar"?remove_ending("def")}

will print:

abc
foobar

rtf (deprecated)

Note:

2.3.24 中引入的auto-escaping mechanism不推荐使用此内置函数。通常,为了防止双重转义和混乱,在启用自动转义的地方使用此内置符号是parse-time error。为了帮助迁移,此内置插件无提示地绕过 RTF 标记输出值而不更改它们。

字符串为 RTF 文本(RTF 文本)。也就是说,所有字符串:

  • \替换为\\

  • {替换为\{

  • }替换为\}

split

它用于将一个字符串沿着另一个字符串的出现拆分为一系列字符串。例如:

<#list "someMOOtestMOOtext"?split("MOO") as x>
- ${x}
</#list>

will print:

- some
- test
- text

请注意,假定所有出现的分隔符都在新项之前(带有"r"标志的除外-稍后请参见),因此:

<#list "some,,test,text,"?split(",") as x>
- "${x}"
</#list>

will print:

- "some"
- ""
- "test"
- "text"
- ""

split接受可选的flags parameter作为其第二个参数。 r(正则表达式)标志存在历史故障;它将从结果列表的末尾删除空元素,因此在最后一个示例中使用?split(",", "r"),输出中将缺少最后一个""

如果第一个参数为空字符串,则该字符串将被拆分为字符(因为 FreeMarker 2.3.28-较早的版本仅适用于r标志)。

Note:

要检查字符串是否以某些内容结尾并附加其他内容,请使用sure_ends_with 内置

starts_with

返回此字符串是否以指定的子字符串开头。例如"redirect"?starts_with("red")返回布尔值true。同样,"red"?starts_with("red")将返回true

Note:

要检查字符串是否以某个东西开头,否则以开头,请使用sure_starts_with 内置

字符串(与字符串值一起使用时)

不执行任何操作,仅按原样返回字符串。唯一的 exception 是,如果该值为多类型值(例如,它同时是字符串和序列),则结果值将只是一个简单的字符串,而不是多类型值。这可以用来防止多重 Importing 的伪像。

substring (deprecated)

Note:

从 FreeMarker 2.3.21 开始,此内建版本已被slicing expressions弃用,例如str[from..<toExclusive]str[from..]str[from..*maxLength]

如果正在处理 XML,则发出警告:由于切片表达式同时适用于序列和字符串,并且由于 XML 节点通常同时同时是序列和字符串,因此等效表达式为someXmlNode?string[from..<toExclusive]exp?string[from..],因为不使用?string它将切片节点 Sequences 而不是节点的文本值。

Note:

方便的内置方法涵盖了一些字符串切片的典型用例:remove_beginningremove_endingkeep_beforekeep_afterkeep_before_lastkeep_after_last

剧情简介:exp?substring(from, toExclusive),也可以称为exp?substring(from)

字符串的子字符串。 from是第一个字符的索引。它必须是一个至少为 0 且小于或等于toExclusive的数字,否则错误将中止模板处理。 toExclusive是子字符串的最后一个字符之后的字符位置的索引,换句话说,它比最后一个字符的索引大一个。它必须是一个至少为 0 且小于或等于字符串长度的数字,否则错误将中止模板处理。如果省略toExclusive,则默认为字符串的长度。如果参数是不是整数的数字,则将仅使用数字的整数部分。

Example:

- ${'abc'?substring(0)}
- ${'abc'?substring(1)}
- ${'abc'?substring(2)}
- ${'abc'?substring(3)}

- ${'abc'?substring(0, 0)}
- ${'abc'?substring(0, 1)}
- ${'abc'?substring(0, 2)}
- ${'abc'?substring(0, 3)}

- ${'abc'?substring(0, 1)}
- ${'abc'?substring(1, 2)}
- ${'abc'?substring(2, 3)}

The output:

- abc
- bc
- c
-

-
- a
- ab
- abc

- a
- b
- c

trim

没有前导和尾随空格的字符串。例:

(${"  green mouse  "?trim})

The output:

(green mouse)

truncate, truncate_...

如果有必要将字符串的末尾保留为参数指定的长度,则将其截断,并附加一个终止符字符串(默认为[...])以指示该字符串已被截断。示例(假设默认的 FreeMarker 配置设置):

<#assign shortName='This is short'>
<#assign longName='This is a too long name'>
<#assign difficultName='This isoneveryverylongword'>

No truncation needed:
${shortName?truncate(16)} 

Truncated at word boundary:
${longName?truncate(16)}

Truncated at "character boundary":
${difficultName?truncate(16)}
No truncation needed:
This is short

Truncated at word boundary:
This is a [...]

Truncated at "character boundary":
This isonev[...]

以上注意事项:

  • 如果字符串的长度未超过指定的长度(在这种情况下为 16),则返回该字符串。

  • 当字符串超过该长度时,将其末端剪断,以使其与添加的终止符字符串(此处为[...])一起不超过 16.为了更好看,结果长度可能小于 16. (请参阅下文)。实际上,当所需长度比单独的终止符字符串短时,结果长度也可以大于参数长度,在这种情况下,终止符仍按原样返回。另外,默认算法以外的其他算法可能会选择返回更长的字符串,因为 length 参数原则上只是暗示所需的视觉长度。

  • truncate倾向于在单词边界处进行剪切,而不是在中间单词处进行剪切,但是,如果这样做的结果是比参数指定的长度的 75%短,则它会回切到中间单词处。在以上示例的最后一行中,“ This [...]”将太短(11 <16 * 75%),因此将其改为中间词。

  • 如果剪切发生在单词边界,则单词 end 和终止符字符串之间有一个空格,否则它们之间没有空格。仅将空格视为单词分隔符,而不将其用作标点符号,因此通常可以得出直观的结果。

调整截断规则

通过设置truncate_builtin_algorithm配置设置,可以高度配置截断规则。这可以由程序员(而不是模板作者)完成,因此,有关更多详细信息和示例,请参阅Configurable.setTruncateBuiltinAlgorithm的 JavaDoc。

截断规则也可以在模板中受到较小程度的影响:

  • 指定截断是否应发生在单词边界处:

  • truncate_w将始终在单词边界处截断。例如,difficultName?truncate_w(16)返回“ This [...]”,而不是“ This isonev [...]”(如先前示例所示)。

    • truncate_c会截断任何字符,而不仅限于字尾。例如,longName?truncate_c(16)返回“ This is a t [...]”,而不是“ This is a [...]”(如前面的示例所示)。这倾向于使字符串的长度更接近于指定的长度,但仍不是确切的长度,因为它去除了终止符字符串之前的空白,并且如果我们刚好在单词的结尾之后,则重新添加了一个空格,等等。
  • 指定终止符字符串(而不是依赖于其默认值):truncate和所有truncate_...内置插件都具有附加的可选参数。之后,另一个可选参数可以指定终止符字符串的假定长度(否则将使用其实际长度)。如果您发现自己经常指定终止符字符串,则可以肯定应配置默认值(通过truncate_builtin_algorithm configuration-参见前面)。例:

${longName?truncate(16, '...')}
${longName?truncate(16, '...', 1)}
This is a ...
This is a too ...

当终止符字符串以点(.)或省略号()开头时,默认算法将删除终止符所接触的点和椭圆,以防止结尾处有 3 个以上的点:

${'Foo bar.baaz'?truncate(11, '---')}
${'Foo bar.baaz'?truncate(11, '...')} (Not "Foo bar....")
${'Fo bar. baaz'?truncate(11, '...')} (Word separator space prevents touching)
Foo bar.---
Foo bar... (Not "Foo bar....")
Fo bar. ... (Word separator space prevents touching)

使用标记作为终止符字符串

每个内置的截断都有一个变体,其名称以_m结尾(用于标记)。这些允许使用标记(如 HTML)作为终止符,如果您希望终止符的样式与截断文本的样式不同,则这很有用。默认情况下,标记终止符是<span class='truncateTerminator'>[&#8230;]</span>(其中&#8230;打印省略号字符),但是当然可以使用truncate_builtin_algorithm配置设置更改它(请参见前面)。示例(请参阅前面示例中使用的变量):

${longName?truncate_m(16)}
${difficultName?truncate_w_m(16)}
${longName?truncate_c_m(16)}
This is a <span class='truncateTerminator'>[&#8230;]</span>
This <span class='truncateTerminator'>[&#8230;]</span>
This is a to<span class='truncateTerminator'>[&#8230;]</span>

上面请注意,截断内置项将终止符字符串视为仅 3 个字符长('[''…'']'),因为终止符字符串内部仅计算 HTML/XML 标签和 Comments 之外的字符,并且它们也可以解释数字字符引用(但不解释其他实体引用)。 (当他们决定终止符以点或省略号开头时,也是如此;前面的标记/Comments 被跳过,等等.)

如果使用标记终止符(如上),则truncate..._m内置返回值也将是标记,这意味着auto-escaping不会转义它。当然,截断的字符串本身的内容仍将自动转义:

<#ftl output_format='HTML'>
${'This is auto-escaped: <span>'}
${'This is auto-escaped: <span>, but not the terminator string'?truncate_m(41)}
This is auto-escaped: &lt;span&gt;
This is auto-escaped: &lt;span&gt;, but not <span class='truncateTerminator'>[&#8230;]</span>

uncap_first

cap_first相反。字符串中第一个单词的字符串不大写。

upper_case

字符串的大写版本。例如"GrEeN MoUsE"将是"GREEN MOUSE"

url

Note:

从 FreeMarker 2.3.1 开始可以使用此内置功能。它在 2.3 中不存在。

URL 转义后的字符串。这意味着所有非 US-ASCII 和保留的 URL 字符都将使用%XX进行转义。例如:

<#assign x = 'a/b c'>
${x?url}

输出将是(假设用于转义的字符集是与 US-ASCII 兼容的字符集):

a%2Fb%20c

请注意,它会转义所有个保留的 URL 字符(/=&等),因此此编码可用于编码查询参数值,例如:

<a href="foo.cgi?x=${x?url}&y=${y?url}">Click here...</a>

Note:

上面根本不需要 HTML 编码(?html),因为 URL 转义无论如何都会转义所有保留的 HTML 字符。但是请注意:总是用属性引号引起来,并且总是用普通引号("),而不用撇号('),因为 URL 转义不会使撇号引起来。

要进行 URL 转义,必须选择charset并将其用于计算转义的部分(%XX)。如果您是 HTML 页面的作者,但是您不太了解这一点,请不要担心:程序员应该配置 FreeMarker,以便默认情况下使用正确的字符集(程序员:请参见下文...)。如果您是技术性更高的用户,那么您可能想知道所使用的字符集是由url_escaping_charset设置指定的,可以在模板执行时间中设置(或最好由程序员更早地设置)。例如:

<#--
  This will use the charset specified by the programmers
  before the template execution has started.
-->
<a href="foo.cgi?x=${x?url}">foo</a>

<#-- Use UTF-8 charset for URL escaping from now: -->
<#setting url_escaping_charset="UTF-8">

<#-- This will surely use UTF-8 charset -->
<a href="bar.cgi?x=${x?url}">bar</a>

此外,您可以为转义的单个 URL 显式指定一个字符集作为内置参数:

<a href="foo.cgi?x=${x?url('ISO-8895-2')}">foo</a>

如果内置的url没有参数,则它将使用指定的字符集作为url_escaping_charset设置的值。此设置应由包含 FreeMarker 的软件(例如 Web 应用程序框架)进行设置,因为默认情况下未设置(null)。如果未设置,则 FreeMarker 会使用output_encoding设置的值进行回退,该值也是默认情况下未设置的,因此这也是封闭软件的任务。如果也未设置output_encoding设置,则无法执行内置的无参数url,这将导致执行时间错误。当然,带有参数的url内置参数始终有效。

可以使用setting指令在模板中设置url_escaping_charset,但这是一种不好的做法,至少在 true 的 MVC 应用程序中。不能使用setting指令设置output_encoding设置,因此这肯定是封闭软件的任务。您可能会找到有关此here...的更多信息

url_path

Note:

从 FreeMarker 2.3.21 开始,此内置功能可用。

内置 URL相同,除了它不转义斜杠(/)字符。这意味着用于将使用斜杠(而不是反斜杠!)的路径(例如来自 OS 或某些内容存储库的路径)转换为可以插入 URL 的路径。需要进行此转换的最常见原因是文件夹名称或文件名可能包含非 US-ASCII 字母(“国家”字符)。

Note:

就像内置 URL一样,必须在 FreeMarker 配置设置中设置所需的 URL 转义字符集(或作为后退,输出编码),否则内置错误。或者,您必须指定somePath?url_path('utf-8')这样的字符集。

word_list

一个序列,该序列按出现在字符串中的 Sequences 包含字符串的所有单词。单词是连续的字符序列,包含除white-space之外的任何字符。例:

<#assign words = "   a bcd, .   1-2-3"?word_list>
<#list words as word>[${word}]</#list>

will output:

[a][bcd,][.][1-2-3]

xhtml (deprecated)

Note:

2.3.24 中引入的auto-escaping mechanism不推荐使用此内置函数。通常,为了防止双重转义和混乱,在启用自动转义的地方使用此内置符号是parse-time error。为了帮助迁移,此内置插件无提示地绕过 HTML 标记输出值而不更改它们。

字符串为 XHTML 文本。也就是说,所有字符串:

  • <替换为&lt;

  • >替换为&gt;

  • &替换为&amp;

  • "替换为&quot;

  • '替换为&#39;

此内置和xml内置之间的唯一区别是xhtml内置将'转换为&#39;而不是&apos;,因为某些较旧的浏览器不知道&apos;

Warning!

插入属性值时,请始终将其引号,否则攻击者可能会利用它!这是错误的:<input name="user" value=${user?xhtml}/>。这些很好:<input name="user" value="${user?xhtml}"/><input name="user" value='${user?xhtml}'/>

xml (deprecated)

Note:

2.3.24 中引入的auto-escaping mechanism不推荐使用此内置函数。通常,为了防止双重转义和混乱,在启用自动转义的地方使用此内置符号是parse-time error。为了帮助迁移,此内置插件无提示地绕过 XML 和 HTML 标记输出值而不更改它们。

字符串为 XML 文本。也就是说,所有字符串:

  • <替换为&lt;

  • >替换为&gt;

  • &替换为&amp;

  • "替换为&quot;

  • '替换为&apos;

Warning!

插入属性值时,请始终引用该属性,否则攻击者可能会利用它!这是错误的:<input name="user" value=${user?xml}/>。这些很好:<input name="user" value="${user?xml}"/><input name="user" value='${user?xml}'/>

Common flags

许多内置字符串都接受可选的字符串参数,即所谓的“标志”。在此字符串中,每个字母都会影响内置行为的某个方面。例如,字母i表示内置函数不应区分同一字母的大小写形式。标志字符串中字母的 Sequences 不重要。

这是字母(标志)的完整列表:

  • i:不区分大小写:请勿区分同一字母的大小写。

  • f:仅第一位。也就是说,替换/查找/等。只有第一次出现。

  • r:要查找的子字符串是regular expression。 FreeMarker 使用在http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html处描述的正则表达式的变体(请注意,某些模式功能的存在取决于所使用的 Java 版本)。

  • m:用于正则表达式的多行模式。在多行模式下,表达式^$分别在行终止符或字符串结尾之后或之前匹配。默认情况下,这些表达式仅在整个字符串的开头和结尾匹配。请注意,^$与换行符本身不匹配。

  • s:为正则表达式启用全点模式(与 Perl 单行模式相同)。在全点模式下,表达式.匹配任何字符,包括行终止符。默认情况下,此表达式与行终止符不匹配。

  • c:允许在正则表达式中包含空格和 Comments。

Example:

<#assign s = 'foo bAr baar'>
${s?replace('ba', 'XY')}
i: ${s?replace('ba', 'XY', 'i')}
if: ${s?replace('ba', 'XY', 'if')}
r: ${s?replace('ba*', 'XY', 'r')}
ri: ${s?replace('ba*', 'XY', 'ri')}
rif: ${s?replace('ba*', 'XY', 'rif')}

这输出:

foo bAr XYar
i: foo XYr XYar
if: foo XYr baar
r: foo XYAr XYr
ri: foo XYr XYr
rif: foo XYr baar

这是使用这些公共标志的内置表,并支持以下标志:

Built-ini(忽略大小写)r(常规)m(多行模式)s(全点模式)c(空白和 Comments)f(仅第一个)
replaceYesYes仅适用于r仅适用于r仅适用于rYes
splitYesYes仅适用于r仅适用于r仅适用于rNo
matchesYesIgnoredYesYesYesNo
keep_afterYesYesYesYesYesIgnored
keep_after_lastYesYesYesYesYesIgnored
keep_beforeYesYesYesYesYesIgnored
keep_before_lastYesYesYesYesYesIgnored
ensure_starts_withYesIgnoredYesYesYesIgnored