Chinaunix首页 | 论坛 | 博客
  • 博客访问: 706602
  • 博文数量: 95
  • 博客积分: 1773
  • 博客等级: 上尉
  • 技术积分: 1653
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-17 23:28
文章分类
文章存档

2018年(2)

2017年(10)

2016年(7)

2015年(48)

2014年(2)

2013年(2)

2012年(2)

2011年(7)

2010年(7)

2009年(3)

2008年(1)

2007年(4)

分类: LINUX

2017-10-16 11:02:03

bash 环境下中文字符处理

相关问题

其实这个内容应该更准确的界定为bash环境下非英文字符的处理,但由于我们主要涉及的是中文,或者中英混合文字的处理,所以本文以此为题。

这个问题产生的背景是在处理混合了中英文字符(含标点符号)的内容,用于生成某背景下的图片时,因 为英文字符(含标点,下同)只占1个字符位宽,中文字符(含全角标点)则占2个字符位宽,为了好看,需要精确计数各种字符数量,所以产生了本问题。

处理方法

通过2次替换过滤,产生2种输出,分别是中文字符串和英文字符串,分别计数。 拟处理的字符串为 ASTRING,例如

ASTRING="1一2二a三B四-五:六 七\""

则输出中文字符串为

CSTRING=$( echo ${ASTRING} | sed -n "s/[[:lower:][:upper:][:digit:][:blank:][:punct:]]//gp" )

CSTRING中则是所有的中文字符,

则输出英文字符串为

BSTRING=$( echo ${ASTRING} | sed -n "s/[^[:lower:][:upper:][:digit:][:blank:][:punct:]]//gp" )

BSTRING中则是所有的英文字符,

但这样处理在纯中文或者纯英文的字符串时都会出错(BSTRING和CSTRING均为空),所以需要进行前置检测。

检测方法是,运行

TEST1=$( echo ${ASTRING} | grep -e "[^[:lower:][:upper:][:digit:][:blank:][:punct:]]" ) TEST2=$( echo ${ASTRING} | grep -e "[[:lower:][:upper:][:digit:][:blank:][:punct:]]" )

则此包含中文时TEST1非空,包含英文时TEST2非空。

这样结合前面的内容就可以较完备的检测处理中文了。

额外的一些信息

POSIX字符集类知识及验证

前面规则式中用到了[:XXXX:]一样的形式,这称为posix字符类,一共有

POSIX字符集类

字符 描述 扩展意义(等效)
[:alnum:] 字母与数字字符 [0-9a-zA-Z]
[:digit:] 数字字符 [a-zA-Z]
[:alpha:] 字母字符 [a-zA-Z]
[:blank:] 空格与制表符 [ \t]
[:cntrl:] 控制字符 [\x01-\x1F]
[:graph:] 可打印与可见字符 [^\x01-\x20]
[:lower:] 小写字符 [a-z]
[:upper:] 大写字符 [A-Z]
[:print:] 可打印字符 [\t\x20-\xFF]
[:punct:] 标点字符 [-!"#$%&'( )*+,./:;<=>?@[\\\]^_'{|}~]
[:space:] 空白字符如空格符、制表符、回车符、换行符、垂直制表符以及换页符 [ \t\r\n\v\f]
[:xdigit:] 用于表示十六进制的字符;在ASCII中,与[0-9A-Fa-f]等效 [0-9A-Fa-f]
[:graph:] 同[:print:],但不包括空格 [\t\x21-\xFF]

表内扩展意义中的\xXX等仅仅表示十六进制编码值,在bash下seded规则式中并不起效(它们仅支持 BASIC REGULAR EXPRESSIONS ———— BRE,基本规则式语法),测试了grep支持,所以必要时字符处理需要采用seded之外的工具,以获得更多便利。

根据这个列表上前面的规则式中[:lower:][:upper:][:digit:]部分理论上可以用[:alnum:]代替,但测试这样是不行的,起码在我的环境

LANG="zh_CN.UTF-8" LANGUAGE="zh_CN:zh"

下是不行的,测试出[:alnum:]实际上包括了所有的可见字符。

字符串中字符计数

对字符串中字符计数有多种方法,主要是:

  1. 利用变量意义扩展,如
echo ${#ASTRING}
  1. 利用wc工具,如
echo ${ASTRING} | wc -c

不过这个只能对英文字符串正确计数,对中文字符串则不对,甚至不同环境计数也不统一。要兼容需要用

echo ${ASTRING} | wc -m

即使这样,你会发型其与用第1种方法计数的结果还有差异,相差1个字符数,这是因为echo输出默认带换行,这个符号也被计数,所以更准确的处理是

echo -n ${ASTRING} | wc -m

这样就和第1种方法得出的结果一致了。

阅读(1812) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~