Tools 是非官方社区Wiki。社区文档正在编写中,欢迎参与。 Wiki编辑答疑群:717421103
版本250722.2
全站通知:

帮助:解析函数/arraysearcharray

来自WIKI实验室WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

Arraysearcharray是一个解析函数。帮助:解析函数页列出了所有解析函数的说明。

arraysearcharray

数组筛选。出自扩展 Arrays BWIKI和各大Wiki平台广泛使用此扩展。<br>在遥远的未来,它可能与Mediawiki新的并行解析器不兼容,请参阅扩展主页了解更多信息。

从一个数组中筛选出匹配项并写入新数组

支持正则表达式或“整段等值匹配”。可指定起始位置、最大匹配数;当使用正则时,可按捕获组对结果做格式化替换。

语法

{{#arraysearcharray: 新数组名 | 原数组名 | 搜索条件 | 起始索引 | 限制数量 | 转换规则 }}

参数:

  • 新数组名:筛选结果将写入此数组
  • 原数组名:要被筛选的数组
  • 搜索条件:正则表达式或字符串,默认值/^(\s*)$/(匹配空白项)
  • 起始索引:默认 0。从该位置起开始扫描
  • 限制数量:默认不限制。空值或 -1 表示不限制
  • 转换规则:可选,仅当搜索条件为正则时生效。写入结果前对匹配文本做替换,支持用 $1$2… 引用捕获组(整段匹配可用 $0

示例

定义数组:{{#arraydefine:a|apple, bule1, fly, add1,,,, wiki}},值为:apple、bule1、fly、add1、、、、wiki

说明 代码 结果
筛选以 a 开头的值 {{#arraysearcharray: x | a | /^a.+/ }} apple、add1
以 a 开头,从第 2 项开始 {{#arraysearcharray: x | a | /^a.+/ | 2 }} add1
以 a 开头,仅取 1 个命中 {{#arraysearcharray: x | a | /^a.+/ | 0 | 1 }} apple
匹配以数字结尾的元素 {{#arraysearcharray: x | a | /^.*?(\d+)$/ }} bule1、add1
匹配以数字结尾,重排格式 {{#arraysearcharray: x | a | /^.*?(\d+)$/ | | | '''pre-$0''' }} pre-bule1pre-add1
删除空项(仅保留非空白) {{#arraysearcharray: a | a | /\S+/ }} apple、bule1、fly、add1、wiki

底层代码

/** mediawiki-extensions-Arrays-REL1_37 ExtArrays.php
 * search an array and create a new array with all the results. Transforming the new entries before storing them is possible too.
 * usage:
 *   {{#arraysearcharray:arrayid_new|arrayid|needle|index|limit|transform}}
 *
 * "needle" can be a regular expression or a string search value. If "needle" is a regular expression, "transform" can contain
 * "$n" where "n" stands for a number to access a variable from the regex result.
 */
public static function pfObj_arraysearcharray( Parser &$parser, PPFrame $frame, $args ) {
	$store = self::get( $parser );

	// get first two parameters
	$arrayId = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : null;
	$arrayId_new  = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';

	if ( $arrayId === null ) {
		global $egArraysCompatibilityMode;
		if ( !$egArraysCompatibilityMode ) { // COMPATIBILITY-MODE
			$store->setArray( $arrayId_new );
		}
		return '';
	}

	// Get Parameters the other parameters
	$needle       = isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '/^(\s*)$/';
	$index        = isset( $args[3] ) ? trim( $frame->expand( $args[3] ) ) : 0;
	$limit        = isset( $args[4] ) ? trim( $frame->expand( $args[4] ) ) : '';
	$rawTransform = isset( $args[5] ) ? $args[5] : null;

	// also takes care of negative index by calculating start index:
	$validIndex = $store->validate_array_index( $arrayId, $index, false );

	// make sure at least empty array exists but don't overwrite data
	// we still need in case new array ID same as target array ID
	$array = $store->getArray( $arrayId );
	$store->setArray( $arrayId_new );

	if ( $array === null || !$validIndex ) {
		return '';
	}

	// non-numeric limit will be set to 0, except limit was omitted ('')
	$limit = $limit === '' ? -1 : (int)$limit;
	if ( $limit === 0 ) {
		return '';
	}

	$newArr = [];

	$regexFunSupport = self::hasRegexFunSupport();
	if ( !self::isValidRegEx( $needle, $regexFunSupport ) ) {
		$needle = '/^\s*(' . preg_quote( $needle, '/' ) . ')\s*$/';
	}

	// search the array for all matches and put them in the new array
	$total = count( $array );
	for ( $i = $index; $i < $total; $i++ ) {

		$value = $array[ $i ];

		if ( preg_match( $needle, $value ) ) {
			// Found something!
			if ( $rawTransform !== null ) {
				// Transform the matching string. Can we use 'Regex Fun' with special 'e' flag support ?
				if ( $regexFunSupport ) {
					// do the transformation with Regex Fun to support 'e' flag:
					$transform = trim( $frame->expand(
							$rawTransform,
							PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES // leave expanding of templates to 'Regex Fun'
					) );
					$value = ExtRegexFun::doPregReplace(
							$needle,
							$rawTransform,
							$value,
							-1,
							$parser,
							$frame,
							[ ExtRegexFun::FLAG_REPLACEMENT_PARSE ]
					);
				} else {
					// regular preg_replace:
					$transform = trim( $frame->expand( $rawTransform ) );
					$value = preg_replace( $needle, $transform, $value );
				}
			}
			$newArr[] = trim( $value );

			// stop if limit is reached, limit -1 means no limit
			if ( --$limit === 0 ) {
				break;
			}
		}
	}

	// set new array:
	$store->setArray( $arrayId_new, $newArr );
	return '';
}

代码逻辑:

  • 解析参数,包括原数组 ID、新数组 ID、搜索值、起始索引、限制数量和转换规则。
  • 验证索引是否有效,获取原数组,并创建新数组。
  • 对搜索值进行正则表达式验证,如果不是有效的正则表达式,则转换为匹配完整字符串的正则表达式。
  • 遍历原数组,对每个值进行搜索匹配,如果找到匹配项,根据需要进行转换(基于PHP的preg_replace),并将匹配结果存入新数组中,直到达到限制数量或搜索完整个数组。
  • 保存新数组。

实际用例

一些Wiki使用了相关特性,如下所示这个静态列表可能在下列页面更改后过时仅供批判性参考