JavaEye3.0开发手记之二 - rails的UTF-8支持造成的正则表达式问题

本文主要是介绍JavaEye3.0开发手记之二 - rails的UTF-8支持造成的正则表达式问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

rails的ActionView::Helpers::TextHepler模块提供了很多实用的方法,这些方法对于论坛类应用非常有用,例如auto_link这个方法可以自动检测传入字符串当中的URL,并将其自动转换为HTML超链接格式,这对于显示帖子的内容来说很不错。

但是在开发JavaEye3.0的时候,却发现auto_link有bug,一旦帖子当中的URL后面紧跟中文的话,auto_link就会把URL后面所有的中文当做URL的一部分进行格式化,直到碰到空格为止,例如:

[quote]http://www.iteye.com网站很不错[/quote]

就会被格式化为:

[quote]<a href="http://www.iteye.com网站很不错">http://www.iteye.com网站很不错</a>[/quote]

看来得到rails的源代码里找答案了。

打开netbeans,敲快捷键Ctrl+O,在弹出窗口输入:texthelper,回车,netbeans已经帮我打开了text_helper.rb源代码,通过Navigator窗口,很方便的定位到auto_link方法,仔细看一下,原来主要是这个正则表达式在起作用:


AUTO_LINK_RE = %r{
( # leading text
<\w+.*?>| # leading HTML tag, or
[^=!:'"/]| # leading punctuation, or
^ # beginning of line
)
(
(?:https?://)| # protocol spec, or
(?:www\.) # www.*
)
(
[-\w]+ # subdomain or domain
(?:\.[-\w]+)* # remaining subdomains or domain
(?::\d+)? # port
(?:/(?:(?:[~\w\+%-]|(?:[,.;:][^\s$]))+)?)* # path
(?:\?[\w\+%&=.;-]+)? # query string
(?:\#[\w\-]*)? # trailing anchor
)
([[:punct:]]|\s|<|$) # trailing text
}x unless const_defined?(:AUTO_LINK_RE)


但这个正则表达式上看下看,左看右看都没有啥问题阿。于是把这个正则表达式拷贝出来,放在一个ruby文件里面test.rb,一点点单独调试,但怎么调试都正常,即使把上面那个URL放进去,也可以正常截断中文。

难道是因为rails做了手脚?为了验证这一点,在test.rb前面加上如下内容:


ENV["RAILS_ENV"] = "development"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")


再运行test.rb,果然!中文又被包括进去了,看来就是rails做了手脚。

再回过头仔细看这个正则表达式,只有[\w]和字符串处理有关系,为了验证这一点,我们做如下试验:

创建一个char.rb文件,内容如下:


def name
return "范凯"
end


请注意!该文件保存格式请必须使用UTF-8!!
然后打开irb,进行如下交互:

[quote]irb(main):001:0> load "char.rb"
=> true
[color=red]irb(main):002:0> name
=> "\350\214\203\345\207\257"[/color]
irb(main):003:0> name.match /[A-Za-z0-9_]+/
=> nil
irb(main):004:0> name.match /\w+/
=> nil[/quote]

请注意标记为红色的行,在ruby的内存中,中文字符串的编码使用的是unicode格式,中文字符串不能够匹配到/[\w]+/上面去,而/[A-Za-z0-9_]+/与/\w+/是同义词。

好了,现在启动rails的环境:
[quote]$ ./script/console
Loading development environment.
>> load "char.rb"
=> []
[color=red]>> name
=> "鑼冨嚡"[/color]
>> name.match /[A-Za-z0-9_]+/
=> nil
[color=red]>> name.match /\w+/
=> #<MatchData:0x474693c>[/quote][/color]

哈哈,水落石出了!!由于rails的ActiveSupport的引入,在ruby的内存当中,字符串被转换为UTF-8格式了(显示乱码是因为我的Windows操作系统是GBK编码),而中文字符串居然可以匹配/\w+/了!

我们可以看到,由于rails在内存当中以UTF-8格式操作中文字符串,而不是ruby默认的unicode格式,这就导致了正则表达式的歧义:/[A-Za-z0-9_]+/不能匹配中文,但是/\w+/可以匹配中文,但实际上在ruby当中,这两个正则表达式本应该是同义词。

明白了问题的根源,就清楚了如何去解决auto_link的bug,修改正则表达式和相关方法,将\w替换为A-Za-z0-9,并将其放入你的rails项目的application_helper.rb当中,这样就可以在项目启动以后覆盖rails系统类库的定义:


AUTO_LINK_RE = %r{
( # leading text
<\w+.*?>| # leading HTML tag, or
[^=!:'"/]| # leading punctuation, or
^ # beginning of line
)
(
(?:https?://)| # protocol spec, or
(?:www\.) # www.*
)
(
[-0-9A-Za-z_]+ # subdomain or domain
(?:\.[-0-9A-Za-z_]+)* # remaining subdomains or domain
(?::\d+)? # port
(?:/(?:(?:[~0-9A-Za-z_\+%-]|(?:[,.;:][^\s$]))+)?)* # path
(?:\?[0-9A-Za-z_\+%&=.;-]+)? # query string
(?:\#[0-9A-Za-z_\-]*)? # trailing anchor
)
}x unless const_defined?(:AUTO_LINK_RE)

def auto_link_urls(text, href_options = {})
extra_options = tag_options(href_options.stringify_keys) || ""
text.gsub(AUTO_LINK_RE) do
all, a, b, c = $&, $1, $2, $3
if a =~ /<a\s/i # don't replace URL's that are already linked
all
else
text = b + c
text = yield(text) if block_given?
%(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{extra_options}>#{text}</a>)
end
end
end


OK,搞定了,这下auto_link可以正确截断中文了。

这篇关于JavaEye3.0开发手记之二 - rails的UTF-8支持造成的正则表达式问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/174757

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD