没有不值得去解决的问题,也没有不值得去学习的技术!

在 PHP 中,基于 preg_replace 替换一段字符串中的一些敏感字符

最终替换前与替换后的格式对比如下,符合预期
1、在 PHP 中,基于 preg_replace 替换一段字符串中的一些敏感字符。存在的一个问题是,其格式中,可能某一段字符串是不存在的。示例如下


订单备注: 修改为: 是搜索

订单备注: 修改为: 13123123,订单发货备注: 修改为: 321312312

订单发货备注: 修改为: 87987




订单备注:***修改为:***

订单备注:***修改为:***,订单发货备注:***修改为:***

订单发货备注:***修改为:***


2、为何存在如上 3 种格式,原因在于其是基于如下代码生成的


$value = [];
if ($order['remarks'] != $latestOrder['remarks']) {
	$value[] = sprintf(
		'订单备注由%s变更为%s',
		$order['remarks'],
		$latestOrder['remarks']
	);
}
if ($order['remarks_delivery'] != $latestOrder['remarks_delivery']) {
	$value[] = sprintf(
		'订单发货备注由%s变更为%s',
		$order['remarks_delivery'],
		$latestOrder['remarks_delivery']
	);
}
if (!empty($value)) {
	$data[OrderLogConstants::ORDER_REMARK] = implode(',', $value);
}


3、最终实现的代码如下


$originalDescription = $description;
$description = preg_replace('/(订单备注:)[\s\S]*修改为:[\s\S]*(,订单发货备注:)/', '$1***修改为:***,订单发货备注:', $description);
if ($originalDescription == $description) {
	$description = preg_replace('/(订单备注:)[\s\S]*修改为:[\s\S]*/', '$1***修改为:***', $description);
}
$description = preg_replace('/(订单发货备注:)[\s\S]*修改为:[\s\S]*/', '$1***修改为:***', $description);


4、但是,当存在的格式有更多种的时候,比如说超过 10 种以上,在程序中硬编码就不可行了。决定抽象出一个方法



$value = [];
if (trim($order['customer_name']) != trim($latestOrder['customer_name'])) {
	$value[] = sprintf(
		'客户姓名由%s变更为%s',
		$order['customer_name'],
		$latestOrder['customer_name']
	);
}
if ($order['customer_email'] != $latestOrder['customer_email']) {
	$value[] = sprintf(
		'联系邮箱由%s变更为%s',
		$order['customer_email'],
		$latestOrder['customer_email']
	);
}
if ($order['customer_tel'] != $latestOrder['customer_tel']) {
	$value[] = sprintf(
		'联系电话由%s变更为%s',
		$order['customer_tel'],
		$latestOrder['customer_tel']
	);
}
if ($order['customer_country_code'] != $latestOrder['customer_country_code']) {
	$value[] = sprintf(
		'所属国家由%s变更为%s',
		$order['customer_country'],
		$latestOrder['customer_country']
	);
}
if ($order['customer_state'] != $latestOrder['customer_state']) {
	$value[] = sprintf(
		'省/州由%s变更为%s',
		$order['customer_state'],
		$latestOrder['customer_state']
	);
}
if ($order['customer_city'] != $latestOrder['customer_city']) {
	$value[] = sprintf(
		'所属城市由%s变更为%s',
		$order['customer_city'],
		$latestOrder['customer_city']
	);
}
if ($order['customer_zip'] != $latestOrder['customer_zip']) {
	$value[] = sprintf(
		'邮编由%s变更为%s',
		$order['customer_zip'],
		$latestOrder['customer_zip']
	);
}
if (trim($order['customer_address1']) != trim($latestOrder['customer_address1'])) {
	$value[] = sprintf(
		'邮寄地址由%s变更为%s',
		$order['customer_address1'],
		$latestOrder['customer_address1']
	);
}
if (trim($order['customer_address2']) != trim($latestOrder['customer_address2'])) {
	$value[] = sprintf(
		'备用地址由%s变更为%s',
		$order['customer_address2'],
		$latestOrder['customer_address2']
	);
}
if ($order['customer_house_number'] != $latestOrder['customer_house_number']) {
	$value[] = sprintf(
		'门牌号由%s变更为%s',
		$order['customer_house_number'],
		$latestOrder['customer_house_number']
	);
}
if (trim($order['customer_abnnumber']) != trim($latestOrder['customer_abnnumber'])) {
	$value[] = sprintf(
		'收件人税号由%s变更为%s',
		$order['customer_abnnumber'],
		$latestOrder['customer_abnnumber']
	);
}
if (trim($order['customer_billing_address']) != trim($latestOrder['customer_billing_address'])) {
	$value[] = sprintf(
		'账单地址由%s变更为%s',
		$order['customer_billing_address'],
		$latestOrder['customer_billing_address']
	);
}

if (!empty($value)) {
	$data[OrderLogConstants::ORDER_CUSTOMER] = implode(',', $value);
}




$patterns = ['客户姓名:', '联系邮箱:', '联系电话:', '所属国家:', '省/州:', '所属城市:', '邮编:', '邮寄地址:', '备用地址:', '门牌号:', '收件人税号:', '账单地址:'];
$pattern = '修改为:';

/**
 * 对 日志的描述 加密
 * @param string $description
 * @param array $patterns
 * @param string $pattern 要搜索的中间的模式
 * @param array $onePatterns 要搜索的仅替换1处的模式数组
 * @param string $oneSpacePattern 要搜索的仅替换1处的模式的间隔符
 * @param array $noEncryptPatterns 要搜索的不加密的模式数组
 * @return string
 */
private function encrypt(string $description, array $patterns, string $pattern = '变更为', array $onePatterns = [], string $oneSpacePattern = ',', array $noEncryptPatterns = []): string
{
	foreach ($patterns as $key => $otherPattern) {
		unset($patterns[$key]);
		$description = $this->encryptCommonChange($description, $otherPattern, array_values($patterns), $pattern, $onePatterns, $oneSpacePattern, $noEncryptPatterns);
	}

	return $description;
}

/**
 * 对 简单的、公共的 加密的更改,避免穷举遍历(替换1处|不加密|替换2处)
 * @param string $description
 * @param string $startPattern 要搜索的开头的模式
 * @param array $otherPatterns 要搜索的其他模式
 * @param string $pattern 要搜索的中间的模式
 * @param array $onePatterns 要搜索的仅替换1处的模式数组
 * @param string $oneSpacePattern 要搜索的仅替换1处的模式的间隔符
 * @param array $noEncryptPatterns 要搜索的不加密的模式数组
 * @return string
 */
private function encryptCommonChange(string $description, string $startPattern, array $otherPatterns, string $pattern = '变更为', array $onePatterns = [], string $oneSpacePattern = ',', array $noEncryptPatterns = []): string
{
	$originalDescription = $description;
	if (in_array($startPattern, $onePatterns)) {
		foreach ($otherPatterns as $otherPattern) {
			if ($originalDescription == $description) {
				$description = preg_replace('/(' . preg_quote($startPattern, '/') . ')[\s\S]*(' . $oneSpacePattern . preg_quote($otherPattern, '/') . ')/', '$1***' . $oneSpacePattern . $otherPattern, $description);
			}
		}
		if ($originalDescription == $description) {
			$description = preg_replace('/(' . preg_quote($startPattern, '/') . ')[\s\S]*/', '$1***', $description);
		}
	} elseif (in_array($startPattern, $noEncryptPatterns)) {
		// 不加密
	} else {
		foreach ($otherPatterns as $otherPattern) {
			if ($originalDescription == $description) {
				$description = preg_replace('/(' . preg_quote($startPattern, '/') . ')[\s\S]*' . $pattern . '[\s\S]*(,' . preg_quote($otherPattern, '/') . ')/', '$1***' . $pattern . '***,' . $otherPattern, $description);
			}
		}
		if ($originalDescription == $description) {
			$description = preg_replace('/(' . preg_quote($startPattern, '/') . ')[\s\S]*' . $pattern . '[\s\S]*/', '$1***' . $pattern . '***', $description);
		}
	}

	return $description;
}



5、最终替换前与替换后的格式对比如下,符合预期。如图1
最终替换前与替换后的格式对比如下,符合预期
图1


客户姓名:常刚修改为:Daly Siennaa,联系邮箱:o.neyandezy@dsydyb.ga修改为:heodloklrs@iubridge.com,邮编:修改为:40291,联系电话:修改为:3421732762,所属城市:修改为:Louisville,邮寄地址:修改为:1214  Montreal Road
客户姓名:***修改为:***,联系邮箱:***修改为:***,邮编:***修改为:***,联系电话:***修改为:***,所属城市:***修改为:***,邮寄地址:***修改为:*** 

联系电话:4913106683312修改为:1(310)668-3312,省/州:修改为:New York,邮寄地址:Amsterdam Ave Apt 214修改为:Amsterdam Ave 509 Apt 214
联系电话:***修改为:***,省/州:***修改为:***,邮寄地址:***修改为:***


需要长期技术维护或远程问题排查?

我是拥有 15+ 年经验的 PHP / Go 后端工程师,长期关注已有系统维护、Bug 修复、性能优化、服务器排查、WordPress 网站维护和小功能迭代。

如果你的项目遇到以下情况,可以先从一次小问题排查开始合作:

  • ✅ PHP / Laravel / Yii2 老项目无人维护
  • ✅ Go / Gin 后端接口需要排查或优化
  • ✅ WordPress 网站访问慢、报错或插件冲突
  • ✅ Nginx / MySQL / Redis / Linux 服务器异常
  • ✅ CDN / Cloudflare / DNS / HTTPS 配置问题
  • ✅ 需要长期远程技术支持或兼职维护

更多介绍请查看:关于我 & 合作

微信:13980074657
邮箱:shuijingwanwq@gmail.com
Telegram:@shuijingwan
GitHub:https://github.com/shuijingwan

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理