极湖

无不用其“极”

Subscribe to RSS feed

Posts tagged with "Regex"

用php给文本中的关键词加上链接

,

百度知道上收到到一条求助: 如何使用php给文本中的关键词加上链接 这个问题看似简单,做起来却有些麻烦,我用一种不太聪明的方式实现:
  1. 把已有的关键字链接替换成文字
  2. 把关键字从长至短排列
  3. 从长至短替换关键字为链接,替换的同时查找有没有包含其他关键字,如果有,把其中子关键字替换成{子关键字的md5值}
  4. 把{子关键字的md5值}替换回来
代码如下:
<?php
/**
 * 按长度排序(降序)
 */
function _sortDesc($a, $b) {
	return (strlen($a[0]) < strlen($b[0])) ? 1 : -1;
}

$linkDefs = array(
  '茶叶,111.htm',
  '中国茶叶大观,222.htm',
);

$linkMap = array();
foreach($linkDefs as $row) {
	$linkMap[] = explode(',', $row);
}

$str = '
这儿是茶叶的链接。<br />
这儿是中国茶叶大观的链接。<br />
这儿是<a href="111.html">茶叶</a>的现有链接。<br />
这儿是<a href="222.html">中国茶叶大观</a>的现有链接。<br />
';

//把原有的链接替换成文字
foreach($linkMap as $row) {
	$str = preg_replace('/(<a.*?>\s*)('.$row[0].')(\s*<\/a>)/sui', '${2}', $str);
}

//关键字从长至短排序
usort($linkMap, '_sortDesc');

$tmpKwds = array(); //存放暂时被替换的子关键字

foreach($linkMap as $i=>$row) {
	list($kwd, $url) = $row;
	for($j=$i+1; $j<count($linkMap); $j++) {
		$subKwd = $linkMap[$j][0];
		//如果包含其他关键字,暂时替换成其他字符串
		if(strpos($kwd, $subKwd) !== false) {
			$tmpKwd = '{'.md5($subKwd).'}';
			$kwd = str_replace($subKwd, $tmpKwd, $kwd);
			$tmpKwds[$tmpKwd] = $subKwd;
		}
	}
	//把文字替换成链接
	$str = preg_replace('/('.$row[0].')/sui', '<a href="'.$row%5B1%5D.'">'.$kwd.'</a>', $str, 5);  // 最多替换5次
}

foreach($tmpKwds as $tmp=>$kwd) {
	$str = str_replace($tmp, $kwd, $str);
}

echo $str;
?>
程序输出:
这儿是<a href="111.htm">茶叶</a>的链接。<br />
这儿是<a href="222.htm">中国茶叶大观</a>的链接。<br />

这儿是<a href="111.htm">茶叶</a>的现有链接。<br />
这儿是<a href="222.htm">中国茶叶大观</a>的现有链接。<br /> 

文本编辑常用正则表达式(不定期更新)

,

从事代码别想工作时间长了,用正则表达式查找替换文本也就成为家常便饭。
编辑文本,如果不会用正则表达式,效率要打折扣,这是我的一点体会。

记录一下最近常用的表达式:

-------------------------------
js多余逗号
,[\s\r\n]*\}
,[\s\r\n]*\]

-------------------------------
行尾空格
([^\s])\s+$
-------------------------------
一个或多个汉字
[\x{4e00}-\x{9fa5}]+
-------------------------------
php 变量名替换: $var_name -> $varName
替换前: (\$\w+)_(\w)(\w*)
替换后: \1\U\2\L\3
-------------------------------
从HTML文本抽取 name="..." 中的name属性
替换前: .*\sname="([^"]+)".*
替换后: \1
-------------------------------

其他常用的暂时想不起来,以后补充。

注:
以上表达式,主要在 EmEditor 下使用。
EmEditor 下正则替换很简单,替换字符串()中的内容,在被替换的字符串里,按顺序是 \1 \2 \3 ...

PHP 正则表达式常用操作符

,

这东西太常用,有时候又记不住,每次上Google查询,太费事,所以贴一个在这儿。
.(句点)    匹配所有单个字符
^(脱字符号)    匹配出现在行或字符串开头的空字符串
$(美元符号)    匹配出现在行尾的空字符串
A    匹配大写字母 A 
a    匹配小写字母 a 
\d    匹配所有一位数字
\D    匹配所有单个非数字字符
\w    匹配所有单个字母或数字字符;同义词是 [:alnum:] 
[A-E]    匹配所有大写的 A、B、C、D 或 E 
[^A-E]    匹配除大写 A、B、C、D 或 E 之外的任何字符
X?    匹配出现零次或一次的大写字母 X 
X*    匹配零个或多个大写字母 X 
X+    匹配一个或多个大写字母 X 
X{n}    精确匹配 n 个大写字母 X 
X{n,m}    至少匹配 n 个且不多于 m 个大写字母 X;如果忽略 m,则表达式将尝试匹配至少 n 个 X 
(abc|def)+    匹配一连串的(最少一个)abc 和 def;abc 和 def 将匹配

一些日文处理的正则表达式(Perl)

, ,

# 半角スペース
$spc = '\x20';

# 全角スペース
$eSpc = '(?:\xA1\xA1)'; # EUC-JP
$sSpc = '(?:\x81\x40)'; # SJIS


# 全角数字 [0-9]
$eLng = '(?:\xA3[\xB0-\xB9])'; # EUC-JP
$sLng = '(?:\x82[\x4F-\x58])'; # SJIS


# 全角小英字 [a-z][/COLOR]
$estr = '(?:\xA3[\xE1-\xFA])'; # EUC-JP
$sstr = '(?:\x82[\x81-\x9A])'; # SJIS


# 全角大英字 [A-Z]
$eStr = '(?:\xA3[\xC1-\xDA])'; # EUC-JP
$sStr = '(?:\x82[\x60-\x79])'; # SJIS


# 全角ひらがな [ぁ-ん]
$eHira = '(?:\xA4[\xA1-\xF3])'; # EUC-JP
$sHira = '(?:\x82[\x9F-\xF1])'; # SJIS


# 全角カタカナ [ァ-ヶ]
$eKana = '(?:\xA5[\xA1-\xF6])'; # EUC-JP
$sKana = '(?:\x83[\x40-\x96])'; # SJIS


# 半角カタカナ [ヲ-゜]
$ekana = '(?:\x8E[\xA6-\xDF])'; # EUC-JP
$skana = '[\xA6-\xDF]'; # SJIS


# EUC-JP文字
$euc1 = '[\x00-\x7F]'; # 1byte EUC-JP文字
$euc2 = '(?:[\x8E\xA1-\xFE][\xA1-\xFE])'; # 2byte EUC-JP文字
$euc3 = '(?:\x8F[\xA1-\xFE][\xA1-\xFE])'; # 3byte EUC-JP文字
$euc = "(?:$euc1|$euc2|$euc3)"; # EUC-JP文字

将 CSV 数据分解为数组的函数

, , ,

在网上找到一个将 CSV 数据行分解为数组的PHP函数,如下:
function splitCsvLine($str) {
    $expr = "/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/";
    $results = preg_split($expr, trim($str));
    return preg_replace("/^\"(.*)\"$/", "$1", $results);
}

由于利用了正则表达式,函数很简洁,功能却是不弱,带引号和不带引号的 CSV 数据,都可以正确分解。

正则表达式递归匹配实例

, ,

用JavaScript实现的例子如下:

var sTxt = '正则表达式【①】查找【②】替换【③】';
sTxt = sTxt.replace(/【([^【】]|【?R】)*】/g, ' 注$& ');
alert(sTxt);


結果:
正则表达式 注【①】 查找 注【②】 替换 注【③】

不包含指定字符串的正则表达式

, ,

命题:

在以下数据中,用正则表达式查找不包含"ab"和“bc”,但包含“cd”的行。

abcdefg
acbdefg
ab
bc
cd
cdxxabxxbc
abcd
cdab
axbxcdxxx



正确结果应该是:

abcdefg
acbdefg
ab
bc
cd
cdxxabxxbc
abcd
cdab
axbxcdxxx



解答一:
^(?!.*ab)(?!.*bc)(?=.*cd).*$

解答二:
^(?!(?=.*(ab|bc)))(?=.*cd).*$

以上解答经 EmEditor 验证,无误。

本文摘自《正規表現パズル》。
以上正则表达式的解释请看原文

正则表达式:给HTML的属性值加引号

, ,

替换前: ([A-Za-z]+)=([#A-Za-z0-9_%]+)
替换后: \1="\2"

这是用EmEditor一次替换的方法,其他支持正则表达式的编辑器应该是大同小异。

目前发现的缺点

content="text/html; charset=utf-8"
会被替换成
content="text/html; charset="utf"-8"

还有JavaScript的变量赋值得地方也需注意。
February 2012
S M T W T F S
January 2012March 2012
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29