2023年政策修订增补工作正在进行中,欢迎参与!
  • Moegirl.ICU:萌娘百科流亡社群 581077156(QQ),欢迎对萌娘百科运营感到失望的编辑者加入
  • Moegirl.ICU:账号认领正在试运行,有意者请参照账号认领流程

User:Selfice/图书馆/帮助:扩展:解析器函数(上)

萌娘百科,万物皆可萌的百科全书!转载请标注来源页面的网页链接,并声明引自萌娘百科。内容不可商用。
跳转到导航 跳转到搜索

#expr

类型 运算符号
分组(括弧) ( )
数字 1234.5   e (2.718)   pi (3.142)
二进制运算符 e   一元 +,-
一元 not ceil trunc floor abs exp ln sin cos tan acos asin atan
二进制 ^
* / div mod
+ -
取整 round
逻辑 = != <> > < >= <=
and
or

这个函数计算数学表达式并返回计算值。 在Scribunto中可以通过mw.ext.ParserFunctions.expr来使用此函数。

{{#expr: 表达式 }}

右表依优先级列出了支持的运算符,运算符的详细说明请见帮助:计算。运算结果的精度和格式受运行wiki服务器操作系统和站点语言的数字格式影响可能存在差异。 如果你想要进行基于日期时间的计算(如检测当前日期时间是否超过指定日期时间),首先用1719001119将日期时间转换为距1970年1月1日的秒数,再对秒数进行加减运算。

四舍五入

将左边的数字四舍五入为1/10的幂的倍数,指数等于右边给出的数字的截断值(truncated value)。

向上、向下取整分别使用ceilfloor

案例 结果 舍入方式
{{#expr: 1/3 round 5 }} 0.33333 最终的数字小于5,所以没有明显的取整发生 (0.333333… → 0.33333)
{{#expr: 1/6 round 5 }} 0.16667 最终的数字大于5,所以被向上取整 (0.166666… → 0.16667)
{{#expr: 8.99999/9 round 5 }} 1 同理,最后一位数因后一位而加1,进而引起了前面的进位 (0.999998… → 1.00000 → 1)
{{#expr: 1234.5678 round -2 }} 1200 舍入至最近的整百数,负值在小数点左边。
{{#expr: 1234.5678 round 2 }} 1234.57 舍入至最近的整1/100数,因为正值会舍入至小数点右边。
{{#expr: 1234.5678 round 2.3 }} 1234.57 舍入指数的小数点在舍入结果中不起作用
{{#expr: trunc 1234.5678 }} 1234 小数部分被全部舍弃(截断)
四舍五入至最近的整数
{{#expr: 1/3 round 0 }} 0 向下取整至0
{{#expr: 1/2 round 0 }} 1 向上取整至1
{{#expr: 3/4 round 0 }} 1 向上取整至1
{{#expr: -1/3 round 0 }} -0 向上取整至0
{{#expr: -1/2 round 0 }} -1 向下取整至-1
{{#expr: -3/4 round 0 }} -1 向下取整至-1
使用ceil和floor向上或向下取整
{{#expr: ceil(1/3) }} 1 向上取整至1
{{#expr: floor(1/3) }} 0 向下取整至0
{{#expr: ceil(-1/3) }} -0 向上取整至0
{{#expr: floor(-1/3) }} -1 向下取整至-1
{{#expr: ceil 1/3 }} 0.33333333333333 没有取整,因为1本来就是整数
警告: 注意会被解析为(ceil 1)/3,而不是你想象中的ceil(1/3)

字符串

表达式函数只用于仅含有数字和运算符号的表达式,而字母字符串和其它符号不在此列。若需要比较字符串,可以用#ifeq替代。

{{#expr: "a" = "a" }}Expression error: Unrecognized punctuation character """.
{{#expr: a = a }}Expression error: Unrecognized word "a".
{{#ifeq: a | a | 1 | 0 }}1


#if

语法:{{#ifeq: 字符串1 | 字符串2 | 相同时输出值 | 不相同时输出值 }}

常用用法:

  • {{#ifeq:{{{是否实装}}}|是|[[文件:{{{角色名称}}}.png]]| 暂未实装}}

这个函数判断一个字符串是否为空。只包含空格的字符串被视为空字符串。

{{#if: 测试字符串 | 测试字符串非空时的取值 | 测试字符串为空或仅包含空白字符时的取值 }}
{{#if: 参数1 | 参数2 | 参数3 }}

这个函数首先判断参数1是否为空。如果参数1不为空,则输出参数2。如果参数1为空或只包含空白内容(空格、换行等),则输出参数3。

{{#if: | yes | no}}no
{{#if: string | yes | no}}yes
{{#if:      | yes | no}}no
{{#if:| yes | no}}no

字符串内容会被处理为纯文本,因此不会计算数学表达式:

{{#if: 1==2 | yes | no }}yes
{{#if: 0 | yes | no }}yes

最后一个参数(false)可以忽略:

{{#if: foo | yes }}yes
{{#if: | yes }}
{{#if: foo | | no}}

该函数可嵌套。为了做到这一点,嵌套内层的#if函数需要按规则完整填写所有参数以符合#if的参数形式。一般至多可嵌套7层,该数也可能为wiki自身限制和内存限制而有变动。

$code1: 测试字符串 | 字符串非空时的值 | $code2: 测试字符串 | 字符串非空时的值 | 字符串为空(或只有空格)的值 $code3
{{#if: test string | value if test string is not empty | {{#if: test string | value if test string is not empty | value if test string is empty (or only white space) }} }}

你可以在#if条件句中以字符串变量代替测试字符串。在这里,你需要在变量名的后面加上$pipe (分隔符)以正确引用字符串。 (因此如果参数没有值,则计算结果为一个空字符串而非"{{{1}}}"。)

{{#if:{{{1|}}}|你在变量1里面输入了文本|变量1里面没有文本}}

参见帮助:模板中的解析器函数以了解更多关于解释器函数中变量的相关例子。


#ifeq

这个函数判断两个输入字符串是否相同,并根据结果输出两个字符串的其中一个。 如果需要更多的比较和输出字符串,请考虑使用#switch

{{#ifeq: string 1 | string 2 | value if identical | value if different }}

如果两个字符串均为数字,则函数会进行数值的比较:

{{#ifeq: 01 | 1 | equal | not equal}}equal
{{#ifeq: 0 | -0 | equal | not equal}}equal
{{#ifeq: 1e3 | 1000 | equal | not equal}}equal
{{#ifeq: {{#expr:10^3}} | 1000 | equal | not equal}}equal

否则,函数会进行文本的比较(大小写敏感):

{{#ifeq: foo | bar | equal | not equal}}not equal
{{#ifeq: foo | Foo | equal | not equal}}not equal
{{#ifeq: "01" | "1" | equal | not equal}}not equal  (对比上面没有引号的例子)
{{#ifeq: 10^3 | 1000 | equal | not equal}}not equal  (对比上面带有#expr的例子,会先回传一个有效的整数)

作为例子,考虑一个已存在的模板Template:Timer,该模板利用解析器来选择两个标准时间,short和long。 它以参数作为第一个输入来比较字符串“short”–这没有约定顺序,但是如果参数在第一个则更容易理解。 模板代码定义为:

{{#ifeq: {{{1|}}} | short | 20 | 40 }}

会产生如下结果:

{{timer|short}}20
{{timer|20}}40
{{timer}}40
警告: 在数值比较结果上,#ifexpr不总是和解释器#ifeq#switch保持一致。 后面两种比较相对于#ifexpr而言更加精确,因而未必返回相同结果。

考虑比较下面两个仅有最后一位数不同的数:

{{#ifeq: 12345678901234567 | 12345678901234568 | equal | not equal}}not equal
{{#switch: 12345678901234567 | 12345678901234568 = equal | not equal}}not equal

因为#ifeq#switch使用的PHP会比较两个整数类型的数,会正确返回预期结果。 然而用#ifexpr比较相同的两个数时:

{{#ifexpr: 12345678901234567 = 12345678901234568 | equal | not equal}}equal

对于不同的数字,结果实际上是不正确的。 造成#ifexpr出错行为的原因是MediaWiki将两个数依字面表达理解成了浮点数,而对于像这样的大数,转换为浮点数由于精度误差会存储为一样的数值,导致出错。

警告: 任何的解析器标签和其它的解释器函数,用在解析器函数中时,都一定会被一个临时生成的独一无二的标识码替代。这会影响如下比较:
{{#ifeq: <nowiki>foo</nowiki> | <nowiki>foo</nowiki> | equal | not equal}}not equal
{{#ifeq: <math>foo</math> | <math>foo</math> | equal | not equal}}not equal
{{#ifeq: {{#tag:math|foo}} | {{#tag:math|foo}} | equal | not equal}}not equal
{{#ifeq: [[foo]] | [[foo]] | equal | not equal}}equal如果被比较的字符串由相等的模板调用提供,且模板包含这些标签,则条件视为真,但如果是两个不同的模板,即使有包含这些内容的相同内容,也是视为假。
警告: 随网站配置的变化,含有页面名字的魔术字的字符串的字面比较可能会发生错误。 比如说,{{FULLPAGENAME}}这一魔术字随wiki的变化,可能在返回时使开头字母变成大写,也会用下划线替代空格。

为了解决这个问题,将这个魔术字应用到两个参数上:

{{#ifeq: {{FULLPAGENAME: L'Aquila}} | {{FULLPAGENAME}} | equal | not equal}}equal


#switch

该函数将一个输入值同若干个测试用例(test cases)做比较,如果找到匹配,返回有关联的字符串。

{{#switch: comparison string
 | case = result
 | case = result
 | ...
 | case = result
 | default result
 }}

例如:

{{#switch: baz | foo = Foo | baz = Baz | Bar }}Baz
{{#switch: foo | foo = Foo | baz = Baz | Bar }}Foo
{{#switch: zzz | foo = Foo | baz = Baz | Bar }}Bar

含有部分嵌入包含标记的$switch会影响到能让不熟悉模板代码的编辑者查看和编辑可配置元素的配置文件。

默认

如果comparison string不能与任何case匹配,则返回default result

{{#switch: test | foo = Foo | baz = Baz | Bar }}Bar

在这种语法中,默认返回值必须是函数的最后一个参数,而且不能包含原始等号(不带{{}}的等号)。 否则,就会解析为样例比较,无匹配的样例时不显示文本。 这是因为默认值没有定义(是空的)。 如果有样例匹配,则返回关联的字符串。

{{#switch: test | Bar | foo = Foo | baz = Baz }}
{{#switch: test | foo = Foo | baz = Baz | B=ar }}
{{#switch: test | test = Foo | baz = Baz | B=ar }}Foo

你也可以将case字符串设为#default从而清楚地声明默认值。

{{#switch: comparison string
 | case = result
 | case = result
 | ...
 | case = result
 | #default = default result
 }}

这种方式声明的默认结果可以放在函数的任何地方:

{{#switch: test | foo = Foo | #default = Bar | baz = Baz }}Bar

如果"default"参数被省略,且没有找到匹配,则不返回结果:

{{#switch: test | foo = Foo | baz = Baz }}

分组结果

该函数允许有“跌落”值,多个"case"字符串返回相同的"result"字符串,从而减少重复。

{{#switch: comparison string
 | case1 = result1
 | case2 
 | case3 
 | case4 = result234
 | case5 = result5
 | case6 
 | case7 = result67
 | #default = default result
 }}

在本例中,第二、三、四个分支都会返回"result234",第六和第七个分支都会返回"result67"。 上述案例中,最后一个参数中的“#default = ”可以省略。

带有参数使用

该函数允许将参数用作测试字符串。 在本例中,不必将管道符放在参数名称后面,因为你不太可能需要选择字符串“{{{parameter name}}}”作为样例。 ((如果没有管道符,且参数不存在或没有值,则参数就会显示为这样。) 参见帮助:模板中的解析器函数。)

{{#switch: {{{1}}} | foo = Foo | baz = Baz | Bar }}

上面的例子中,如果{{{1}}}等于foo,函数返回Foo。 如果等于baz,函数返回Baz。 如果参数是空的或者不存在,函数返回Bar

上面的这些中,也可以将样例组合起来以返回单个结果。

{{#switch: {{{1}}} | foo | zoo | roo = Foo | baz = Baz | Bar }}

如果{{{1}}}等于foozooroo,函数返回Foo。 如果等于baz,函数返回Baz。 如果参数是空的或者不存在,函数返回Bar

而且,如果你希望在测试参数不能匹配任何样例时不返回任何内容,可以省略默认结果。

{{#switch: {{{1}}} | foo = Foo | bar = Bar }}

在本例中,如果{{{1}}}存在且等于foobar,则分别返回FooBar,否则不返回任何内容。

这样做相当于将默认值声明为空。

{{#switch: {{{1}}} | foo | zoo | roo = Foo | baz = Baz | }}

如果由于某些原因需要将样例设置为{{{parameter name}}},则函数在参数不存在或没有值的情况下返回该样例的结果。 参数需要存在且拥有不同于字符串“{{{parameter name}}}”的值以返回函数的默认结果。

(若{{{1}}}不存在或者是空的):
{{#switch: {{{1}}} | {{{1}}} = Foo | baz = Baz | Bar }}Foo
(若{{{1}}}的值为test):
{{#switch: {{{1}}} | {{{1}}} = Foo | baz = Baz | Bar }}Bar
(若{{{1}}}的值为“{{{1}}}”):
{{#switch: {{{1}}} | {{{1}}} = Foo | baz = Baz | Bar }}Foo

在这样的例子中,你需要给参数添加管道符({{{1|}}})。

比较行为

如同#ifeq那样,若被比较字符串和测试用例字符串都是数字,那么按照数值进行比较;反之若存在一个非纯数字符串,都会按照字符串比较规则进行:

{{#switch: 0 + 1 | 1 = one | 2 = two | three}}three
{{#switch: {{#expr: 0 + 1}} | 1 = one | 2 = two | three}}one
{{#switch: a | a = A | b = B | C}}A
{{#switch: A | a = A | b = B | C}}C

case字符串可以是空的:

{{#switch: | = Nothing | foo = Foo | Something }}Nothing

只要找到一个匹配,后面的case都会忽略:

{{#switch: b | f = Foo | b = Bar | b = Baz | }}Bar
警告: #switch#ifeq的数值比较结果未必一致(参见上面#ifeq部分):
{{#switch: 12345678901234567 | 12345678901234568 = A | B}}B
{{#ifexpr: 12345678901234567 = 12345678901234568 | A | B}}A

原始等号

“case”字符串不能包含原始等号。如果需要在比较串中加入等号,可以使用仅包含一个等号的模板{{=}}来代替=,或者是用HTML标识码&#61;来代替。

例如:

您输入的 您输出的
{{#switch: 1=2
  | 1=2 = raw
  | 1<nowiki>=</nowiki>2 = nowiki
  | 1{{=}}2 = template
  | default
 }}
template
{{#switch: 1=2
  | 1&#61;2 = html
  | default
 }}
html

为助您理解,您可以检查模板:NBA球队代表色。模板:扩展和w:Template:BOTREQ是两个使用该函数的复杂例子。

替换#ifeq

#switch可以用于减少扩展深度。

例如:

  • {{#switch:{{{1}}} |condition1=branch1 |condition2=branch2 |condition3=branch3 |branch4}}

等效于

  • {{#ifeq:{{{1}}}|condition1 |branch1 |{{#ifeq:{{{1}}}|condition2 |branch2 |{{#ifeq:{{{1}}}|condition3 |branch3 |branch4}}}}}}

也就是线性的深度迭代判断:

{{#ifeq:{{{1}}}|condition1
   |<!--then-->branch1
   |<!--else-->{{#ifeq:{{{1}}}|condition2
                 |<!--then-->branch2
                 |<!--else-->{{#ifeq:{{{1}}}|condition3
                               |<!--then-->branch3
                               |<!--else-->branch4}}}}}}

另一方面,对于嵌套在两个分支中的if(以缩进形式呈现,两侧都缩进),替换成switch可能很复杂/不切实际,从而形成对称树:

{{#ifeq:{{{1}}}|condition1
  |<!--then-->branch1t{{
   #ifeq:{{{1}}}|condition2
    |<!--then-->branch1t2t{{#ifeq:{{{1}}}|condition4|<!--then-->branch1t2t4t|<!--else-->branch1t2t4e}}
    |<!--else-->branch1t2e{{#ifeq:{{{1}}}|condition5|<!--then-->branch1t2e5t|<!--else-->branch1t2e5e}}
   }}
  |<!--else-->branch1e{{#ifeq:{{{1}}}|condition3
    |<!--then-->branch1e3t{{#ifeq:{{{1}}}|condition6|branch1e3t6t|branch1e3t6e}}
    |<!--else-->branch1e3e{{
     #ifeq:{{{1}}}|condition7
      |branch1e3e7t
      |branch1e3e7t
     }}
   }}
 }}

下转User:Selfice/图书馆/帮助:扩展:解析器函数(下)