正则表达式(全)

Posted 懂点计算机的小白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正则表达式(全)相关的知识,希望对你有一定的参考价值。

目录

单括号,双括号,中括号,双中括号,大括号

单括号:

双小括号:

中括号:

双中括号:

大括号:

Echo的用法

正则表达式定义:

正则表达式组成

普通字符:

元字符

扩展元字符

使用grep匹配正则

示例:

总结:元字符

正则工具

Cut工具

Sort工具

Uniq工具

Tr工具

Sed工具:

单括号,双括号,中括号,双中括号,大括号

单括号

1.命令组。括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。

2.命令替换。等同于cmd,shell扫描一遍命令行,发现了( c m d ) 结 构 , 便 将 (cmd)结构,便将(cmd)结构,便将(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。有些shell不支持,如tcsh。

3.用于初始化数组。如:array=(a b c d)

双小括号:

1.整数扩展。这种扩展计算是整数型的计算,不支持浮点型。((exp))结构扩展并计算一个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为1,或者 是"假",而一个非零值的表达式所返回的退出状态码将为0,或者是"true"。若是逻辑判断,表达式exp为真则为1,假则为0。

2.只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中,甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制。如:echo $((16#5f)) 结果为95 (16进位转十进制)

3.单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6

4.常用于算术运算比较,双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合C语言运算规则,比如可以直接使用for((i=0;i<5;i++)), 如果不使用双括号, 则为for i inseq 0 4或者for i in 0..4。再如可以直接使用if (($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ]。

((expr  ))通常作为运算的

中括号

1.bash 的内部命令,[和test是等同的。如果我们不用绝对路径指明,通常我们用的都是bash自带的命令。if/test结构中的左中括号是调用test的命令标识,右中括号是关闭条件判断的。这个命令把它的参数作为比较表达式或者作为文件测试,并且根据比较的结果来返回一个退出状态码。if/test结构中并不是必须右中括号,但是新版的Bash中要求必须这样。

2.Test和[]中可用的比较运算符只有=和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq,-gt这种形式。无论是字符串比较还是整数比较都不支持大于号小于号。如果实在想用,对于字符串比较可以使用转义形式,如果比较"ab"和"bc":[ ab \\< bc ],结果为真,也就是返回状态为0。[ ]中的逻辑与和逻辑或使用-a 和-o 表示。且[]前后都有空格。

3.字符范围。用作正则表达式的一部分,描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。

4.在一个array 结构的上下文中,中括号用来引用数组中每个元素的编号。

双中括号

1.[[是 bash 程序语言的关键字。并不是一个命令,[[ ]] 结构比[ ]结构更加通用。在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。

2.支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。

3.使用[[ … ]]条件判断结构,而不是[ … ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。

4.bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。

大括号

1.大括号拓展。(通配(globbing))将对大括号中的文件名做扩展。在大括号中,不允许有空白,除非这个空白被引用或转义。第一种:对大括号中的以逗号分割的文件列表进行拓展。如 touch a,b.txt 结果为a.txt b.txt。第二种:对大括号中以点点(…)分割的顺序文件列表起拓展作用,如:touch a…d.txt 结果为a.txt b.txt c.txt d.txt

2.代码块,又被称为内部组,这个结构事实上创建了一个匿名函数 。与小括号中的命令不同,大括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开,最后一个也必须有分号。的第一个命令和左括号之间必须要有一个空格。也可以用于多行注释,作为函数包起来只是不调用即可。

[ a /< b ]实际上比的是ascll码的值,其中a,b表示的并不是变量,如果需要比较变量则需要在前面增加$符号。

Echo的用法

Echo -n表示不换行输出

Echo -e表示输出转移字符,将转义后的内容输出到屏幕上

常用的转义字符如下:

\\b:转义后相当于按退格键(backspace),但前提是"\\b"后面存在字符;"\\b"表示删除前一一个字符,"\\b\\b”表示删除前两个字符。

\\c:不换行输出,在"\\c"后面不存在字符的情况下,作用相当于echo -n;但是当"\\c"后面仍然存在字符时,"\\c"后面的字符将不会被输出。

\\n:换行,被输出的字符从"\\n"处开始另起一行。

\\f换行,但是换行后的新行的开头位置连接着上一行的行尾;

\\v '与\\f相同;

\\t转以后表示插入tab,即横向制表符;

\\r光标移至行首,但不换行,相当于使用"\\r"以后的字符覆盖"\\r"之前同等长度的字符:但是当"\\r"后面不存在任何字符时,"\\r"前面的字符不会被覆盖

\\\\表示插入"\\"本身;

正则表达式定义

正则表达式,又称正规表达式、常规表达式,使用字符串来描述、匹配一系列符合某个规则的字符串。

正则表达式组成

普通字符

大小写字母、数字、标点符号及一些其他符号

元字符:

在正则表达式中具有特殊意义的专用字符

元字符

\\:转义字符,\\!、\\n等

^:匹配字符串开始的位置

例: ^a、^the、^#

$:匹配字符串结束的位置

例: word$

.:匹配除\\n之外的任意的一个字符

例: go.d、g..d

*:匹配前面子表达式0次或者多次

例:goo*d、go.*d

[list]:匹配list列表中的一个字符

例: go[ola]d,[abc]、[a-z]、[a-z0-9]

[^list]:匹配任意不在list列表中的一个字符

例: [^a-z]、[^0-9]、[^A-Z0-9]

\\n,m\\:匹配前面的子表达式n到m次,有\\n\\、\\n,\\、\\n,m\\三种格式

例:go\\2\\d、go\\2,3\\d、go\\2,\\d

扩展元字符

       +:匹配前面子表达式1次以上

例: go+d,将匹配至少一个o

?:匹配前面子表达式0次或者1次

例: go?d,将匹配gd或god

():将括号中的字符串作为一个整体

例:(xyz)+,将匹配 xyz 整体1次以上,如xyzxyz

|:以或的方式匹配字条串

例1: good|food,将匹配good或者food

例2: g(oo|la)d,将匹配good或者glad

使用grep匹配正则

       Grep 【选项】 查找条件 目标文件

-w:表示精确匹配

-E :开启扩展(Extend)的正则表达式

-c : 计算找到'搜寻字符串'的次数

-i :忽略大小写的不同,所以大小写视为相同

-o :只显示被模式匹配到的宁符串

-v:反向选择,亦即显示出没有'搜寻字符串′内容的那一行! (反向查找,输出与查找条件不相符的行)--color=auto : 可以将找到的关键词部分加上颜色的显示喔!

-n :顺便输出行号

      

基础正则表达式常见元字符

\\:转义符,将特殊字符进行转义,忽略其特殊意义a\\.b匹配a.b,但不能匹配ajb,.被转义为特殊意义\\\\\\

^:匹配行首,^则是匹配字符串的开始^tux匹配以tux开头的行^^^^

$:匹配行尾,$则是匹配字符串的结尾tux$匹配以tux结尾的行$$$$

.:匹配除了换行符 \\r\\n之外的任意单个字符

[list]:匹配list列表中的一个字符

例: go[ola]d,[abc]、[a-z]、[a-z0-9]

[^list]:匹配任意不在list列表中的一个字符

例: [^a-z]、[^0-9]、[^A-Z0-9]

\\n,m\\:匹配前面的子表达式n到m次,有\\n\\、\\n,\\、\\n,m\\三种格式

例:go\\2\\d、go\\2,3\\d、go\\2,\\d

示例

  1. 查找特定字符

例如在test.txt文件中,多写了一个the,我想单独把the找出来,其中grep中-n表示显示行号,-i是区分大小写

  1. 使用-i命令表示不区分大小写

  1. 使用-v命令查找不包含“the”字符的行,并且配合-n一起使用显示行号

这里我将所有字符全部写在了一行,所以过滤的时候会将整行过滤。

  1. 利用中括号“【】”来查找集合字符

想要查找“shirt”与“short”这两个字符串时,可以发现这两个字符串均包含“sh”与“rt”。此 时执行以下命令即可同时查找到“shirt”与“short”这两个字符串,其中“[]”中无论有几个字符, 都仅代表一个字符,也就是说“[io]”表示匹配“i”或者“o”

4)若查找“oo”前面不是“w”的字符串,只需要通过集合字符的反向选择“[^]”来实现该目的。

例如执行“grep -n‘[^w]oo’test.txt”命令表示在 test.txt 文本中查找“oo”前面不是“w”的字符串。 发现这里还是存在二者均包含“w”。其实通过执行结果就可以看出,符合匹配标准的字符加粗显示,而上述结果中可以得知,

“#woood #”中加粗显示的是“ooo”,而“oo”前面的“o”是符合匹配规则的。同理“#woooooood #” 也符合匹配规则。若不希望“oo”前面存在小写字母,可以使用“grep -n‘[^a-z]oo’test.txt”命令实现,其中“a-z”表示小写字母,大写字母则通过“A-Z”表示。

grep -n '[^a-z]oo' test.txt

发现这里还存在大写字母想要去掉大写字母可以使用[^A-Z]

Grep -n ‘[^A-Z]oo’ test.sh

5)查找包含数字的行可以通过grep -n ‘[0-9]’ test.txt

6)查找行首“^” 与行尾字符:“$基础正则表达式包含两个定位元字符:“^”(行首)与“$”(行尾)。在上面的示例中, 查询“the”字符串时出现了很多包含“the”的行,如果想要查询以“the”字符串为行首的行,则 可以通过“^”元字符来实现”

Grep -n ‘^the’ test.txt

不想以英文开头则使用:

Grep -n ‘^[^a-zA-Z]’

7)”符号在元字符集合“[]”符号内外的作用是不一样的,在“[]”符号内表示反向选择,在“[]” 符号外则代表定位行首。反之,若想查找以某一特定字符结尾的行则可以使用“$”定位符。

例如,执行以下命令即可实现查询以小数点(.)结尾的行。因为小数点(.)在正则表达式

中也是一个元字符(后面会讲到),所以在这里需要用转义字符“\\”将具有特殊意义的字符转

化成普通字符。

Grep -n ‘\\.$’ test.txt

查询空白行:

Grep -n ‘^$’ test.txt

8)过滤空行和注释且注入到文件中

grep -v "^$\\|^#" k.txt >2.txt

9)过滤出ip

Grep -o “[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+” /etc/sysconfig/network-scripts/ifcfg-ens33,+表示钱买你的字符串出现一次或多次,而*表示前面的字符出现0次1次或多次。

10)*表示匹配0次一次或多次

Grep -n “go[al]*d” test

表示其中al可以出现0次1次和多次

Grep -n “go[al]\\2\\d” test表示al出现两次

Grep -n “go[al]\\2,\\d” test在次数的后面加,表示至少不少于2次

Grep -n “go[al]\\2,5\\d” test表示出现2-5次

扩展:

Egrep -E -n ‘go[2]d’ test

Egrep即为grep的增强版功能,在使用的时候需要注意,它不再是使用双引号而是单引号,且在使用时,不需要再加转义符即\\

Egrep -n ‘of|is|on’ test查询of,is,on字符串,其中的|意思并不是管道符而是(或)

Egrep -E -n ‘t(e|s)st’ test

Egrep -E -n ‘t(e|s)*st’ test

查询以t开头t结尾,中间包含至少一个o的字符串,执行以下命令即可实现

Grep -n ‘ts*t’ test

查询以t开头以t结尾,中间的s可有可无的命令

Grep -n ‘ts.*t’ test

查询以t开头以t结尾,且中间出现es次数不限

Grep -n “^t[(es)]t$” test

Grep -n ‘t\\(es\\)\\1,2\\t’ test

总结:元字符

通过上面几个简单的示例,可以了解到常见的基础正则表达式的元字符主要包括以下几个

^ 匹配输入字符串的开始位置。除非在方括号表达式中使用,表示不包含该字符集合。要匹配”^”字符本身,请使用"\\^"

$ 匹配输入字符串的结尾位置。如果设置了RegExp对象的 Multiline属性,则"$”也匹配'\\n'或'\\r’,。要匹配”$"字符本身,请使用”\\$"

. 匹配除"\\r\\n"之外的任何单个字符

\\ 反斜杠,又叫转义字符,去除其后紧跟的元字符或通配符的特殊意义

* 匹配前面的子表达式零次或多次。要匹配“*"字符,请使用“\\*”

[] 字符集合,匹配所包含的任意一个字符。例如,"[abc]"可以匹配"plain"中的"a"

[^] 赋值字符集合,匹配未包含的一个任意字符。例如,"[^abc]"可以匹配"plin"中任何一个字母

[n1-n2] 字符范围,匹配指定范围内的任意一个字符。例如,"[a-z]"可以匹配"a"到"z"范围内的任意一个小写字母字符。注意:只有连字符(-)在字符组内部,并且出现在两个字符之间时,才能表示字符的范围;如果出现在字符组的开头,则只能表示连字符本身

(n  n 是一个非负整数,匹配确定的n次。例如,"o(2"不能匹配"Bob"中的"o",但是能匹配"food"中的"oo"n, n是一个非负整数,至少匹配n次。例如,"o(2,)"不能匹配"Bob"中的"o”,但能匹配""fooood"中的所有o。"o(1,)"等价于"o+"。“o(0,]"则等价于"o*”

n, m m和 n均为非负整数,其中 n<=m,最少匹配n次且最多匹配m 次

正则工具

Cut工具

 列截取工具,cut命令从文件的每一行剪切字节,字符和字段,并将这额字符,字节,字段挟制标准输出,如果不指定file参数,cut命令将读取标准输入,必须指定-b,-c或-f标志之一

选项:

-b:按宁节截取

-c:按字符截取,常用于中文

-d:指定以什么为分隔符截取,默认为制表符

-f:通常和-d一起

案例:

Cat /etc/passwd | cut -d ‘:’ -f 1,表示-d为以:为分隔符,取第一列

Cat /etc/passwd | cut -d ‘:’ -f 1,3表示以:为分隔符取第一列和第三列,不连续

Cat /etc/passwd | cut -d ‘:’ -f 1-3表示以:为分隔符,取一到三列,连续

ls | cut -b 3表示按字节截取

Ls | cut -c 2 上组代码中-d是以第几个字符来截取,而-c则是以中文字符截取

截取331081504806027044938:

Sort工具

  sort是一个以行为单位对文件内容进行排序的工具,也可以根据不同的数据类型来排序,例如数据和字符的排序就不一样,用法:sort 【选项】 【参数】

常用选项:

-t:指定分隔符,默认使用「Tab]键或空格分隔-

-k:指定排序区域,哪个区间排序

-n :按照数字进行排序,默认是以文字形式排序

-u:等同于uniq,表示相同的数据仅显示一行,注意:如果行尾有空格去重就不成功

-r:反向排序,默认是升序,-r就是降序

-o:将排序后的结果转存至指定文件

案例:

Sort sort.txt 什么都不加的话即为默认按第一列升序,字母即从a到z由上

Sort -n -t: -k3 sort.txt 以冒号为分隔符,以数字大小对第三列排序

Sort -nr -t: -k3 passwd.txt 以冒号为分隔符,以数字大小对第三列排序(降序)

Sort -nr -t: -k3 sort.txt -o sort.sh排序后的结果不在屏幕上输出二十输出到sort.sh文件中。

Sort -u sort.txt 避免重复的内容(重复的行可以是不连续的)

Uniq工具

  主要用于去除连续的重复行

注意:是连续的行,所以通常和sort结合使用先排序使之变成连续的行在执行去重操作,否则不连续的重复行不能去重

语法:uniq 【选项】【参数】

常用选项:

-c:对重复的行进行计数;

-d:仅显示重复行;

-u:仅显示出现一次的行;

案例

awk ‘print $1‘ sort.sh | uniq -c 表示相同的字符连续出现的次数

awk ‘print $1‘ sort.sh | uniq -d表示只显示重复的内容

awk ‘print $1‘ sort.sh | uniq -u只显示只出现过一次的行

查看当前状态中是连接状态的网络信息

netstat -natpul | grep "ESTABLISHED" | awk 'print $6 " " $4' | uniq -c

Tr工具

 它可以用一个字符来替换另一个字符,或者可以完全出去一些字符,也可以用来重复字符

语法:tr 【选项】 set1 【set2】

从标准输入中替换,缩减或删除字符,并将结果写道标准输出

常用选项:

-d 删除字符

-s 删除所有重复出现的字符,只保留一个

Cat sort.sh | tr -d “lnjnb”

Cat sort.sh | tr -s “x”

Sed工具

文本处理工具,读取文本内容,根据指定的条件进行处理,如删除、替换、添加等

可在无交互的情况下实现相当复杂的文本处理操作

被广泛应用于Shell脚本,以完成自动化处理任务

sed依赖于正则表达式

工作原理:

Sed命令格式

sed -e '编辑指令' 文件1 文件2 …

sed -n -e '编辑指令' 文件1 文件2 …

sed -i -e '编辑指令' 文件1 文件2

常用选项

-e 指定要执行的命令,只有一个编辑命令时可省略

-n 只输出处理后的行,读入时不显示

-i 直接编辑文件,而不输出结果

-f 用指定的脚本文件来处理输入的文本文件

匹配全限定类名的正则表达式

【中文标题】匹配全限定类名的正则表达式【英文标题】:Regular expression matching fully qualified class names 【发布时间】:2011-07-09 11:40:37 【问题描述】:

在文本中匹配完全限定的 Java 类名的最佳方法是什么?

示例:java.lang.Reflectjava.util.ArrayListorg.hibernate.Hibernate

【问题讨论】:

这些出现在什么上下文中,java import 语句?如果只有 ; 要删除,那么 不要 使用正则表达式 忘记正则表达式;见javax.lang.model.SourceVersion.isName(CharSequence) 【参考方案1】:

Java 完全限定的类名(比如说“N”)具有结构

N.N.N.N

“N”部分必须是 Java 标识符。 Java 标识符不能以数字开头,但在初始字符之后可以使用字母和数字、下划线或美元符号的任意组合:

([a-zA-Z_$][a-zA-Z\d_$]*\.)*[a-zA-Z_$][a-zA-Z\d_$]*
------------------------    -----------------------
          N                           N

它们也不能是保留字(如importtruenull)。如果您只想检查合理性,以上就足够了。如果您还想检查有效性,还必须检查保留字列表。

Java 标识符可以包含任何 Unicode 字母,而不是“仅限拉丁语”。如果您也想检查这一点,请使用 Unicode 字符类:

([\pLetter_$][\pLetter\pNumber_$]*\.)*[\pLetter_$][\pLetter\pNumber_$]*

或者,简称

([\pL_$][\pL\pN_$]*\.)*[\pL_$][\pL\pN_$]*

Java Language Specification, (section 3.8) 包含有关有效标识符名称的所有详细信息。

另请参阅此问题的答案:Java Unicode variable names

【讨论】:

Java 标识符可以以任何货币符号开头,因此 $val、£val 和 ¥val 都是有效的。我认为这适用于类和变量。查看java apidownload.oracle.com/javase/1.5.0/docs/api/java/lang/… @Richard:好的,谢谢你的信息。然后应该使用\pCurrency_Symbol\pSc 而不是$。想想看,一个反复调用isJavaIdentifierPart()isJavaIdentifierStart() 的小型解析器会产生更简洁的代码。 我同意解析器是这样做的方法,这几乎就像 Java 语言设计人员在编写 Character API 时考虑到了这一点;)但是问题是关于正则表达式,所以我认为你已经得到了正确的答案。来自我的 +1。 其实这些方法已经用特殊字符类来表示了。我们只需要匹配一个 Java 标识符就是"(\\pjavaJavaIdentifierStart\\pjavaJavaIdentifierPart*\\.)+\\pjavaJavaIdentifierStart\\pjavaJavaIdentifierPart*"。优雅,你的名字是Java! RegexBuddy 可以处理这个问题:([\pL_\pSc][\pL\pN_\pSc]*\.)+【参考方案2】:

这是一个完整的测试类,基于@alan-moore 的优秀评论

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.regex.Pattern;

import org.junit.Test;

public class ValidateJavaIdentifier 

    private static final String ID_PATTERN = "\\pjavaJavaIdentifierStart\\pjavaJavaIdentifierPart*";
    private static final Pattern FQCN = Pattern.compile(ID_PATTERN + "(\\." + ID_PATTERN + ")*");

    public static boolean validateJavaIdentifier(String identifier) 
        return FQCN.matcher(identifier).matches();
    


    @Test
    public void testJavaIdentifier() throws Exception 
        assertTrue(validateJavaIdentifier("C"));
        assertTrue(validateJavaIdentifier("Cc"));
        assertTrue(validateJavaIdentifier("b.C"));
        assertTrue(validateJavaIdentifier("b.Cc"));
        assertTrue(validateJavaIdentifier("aAa.b.Cc"));
        assertTrue(validateJavaIdentifier("a.b.Cc"));

        // after the initial character identifiers may use any combination of
        // letters and digits, underscores or dollar signs
        assertTrue(validateJavaIdentifier("a.b.C_c"));
        assertTrue(validateJavaIdentifier("a.b.C$c"));
        assertTrue(validateJavaIdentifier("a.b.C9"));

        assertFalse("cannot start with a dot", validateJavaIdentifier(".C"));
        assertFalse("cannot have two dots following each other",
                validateJavaIdentifier("b..C"));
        assertFalse("cannot start with a number ",
                validateJavaIdentifier("b.9C"));
    

【讨论】:

VALID_JAVA_IDENTIFIER 是错误的名称选择,因为该模式代表 FQCN。我建议提取String ID_PATTERN = "\\pjavaJavaIdentifierStart\\pjavaJavaIdentifierPart*" 使其更明显和可读。 @TWiStErRob 不确定您所说的 VALID_JAVA_IDENTIFIER 代表 FQCN 是什么意思?另外,不确定ID_PATTERN 是否更具可读性...感谢您的解释。 有效的 java 标识符可以是方法名、局部变量、类名、子包名等。但是,您的“VALID_JAVA_IDENTIFIER”模式匹配由多个标识符组成的完全限定类名 (FQCN) (每个子包+类名一个)。 FQCN 不是一个有效的 java 标识符,因为它包含点。对于ID_PATTERN,请参阅我对 Jörgen 回答的编辑;更容易查看重复的内容和时间,您也不必滚动或换行。【参考方案3】:

Renaud 提供的模式有效,但他的原始答案总是会在最后回溯。

要优化它,您基本上可以将前半部分与后半部分交换。请注意您还需要更改的点匹配。

以下是我的版本,与原始版本相比,它的运行速度大约是原来的两倍:

String ID_PATTERN = "\\pjavaJavaIdentifierStart\\pjavaJavaIdentifierPart*";
Pattern FQCN = Pattern.compile(ID_PATTERN + "(\\." + ID_PATTERN + ")*");

我不会写cmets,所以我决定写一个答案。

【讨论】:

【参考方案4】:

我(自己)得出了一个类似的答案(如 Tomalak 的答案),类似于 M.M.M.N:

([a-z][a-z_0-9]*\.)*[A-Z_]($[A-Z_]|[\w_])*

在哪里,

M = ([a-z][a-z_0-9]*\.)*
N = [A-Z_]($[A-Z_]|[\w_])*

但是,这个正则表达式(与 Tomalak 的答案不同)做了更多假设:

    包名(M部分)只能小写,M的第一个字符总是小写字母,其余可以混合下划线、小写字母和数字。

    李>

    类名(N 部分)总是以大写字母或下划线开头,其余可以混合下划线、字母和数字。内部类总是以美元符号 ($) 开头,并且必须遵守前面描述的类名规则。

注意:模式\w是字母和数字的XSD模式(不包括下划线符号(_))

希望对您有所帮助。

【讨论】:

【参考方案5】:

以下类验证提供的包名是否有效:

import java.util.HashSet;

public class ValidationUtils 

    // All Java reserved words that must not be used in a valid package name.
    private static final HashSet reserved;

    static 
        reserved = new HashSet();
        reserved.add("abstract");reserved.add("assert");reserved.add("boolean");
        reserved.add("break");reserved.add("byte");reserved.add("case");
        reserved.add("catch");reserved.add("char");reserved.add("class");
        reserved.add("const");reserved.add("continue");reserved.add("default");
        reserved.add("do");reserved.add("double");reserved.add("else");
        reserved.add("enum");reserved.add("extends");reserved.add("false");
        reserved.add("final");reserved.add("finally");reserved.add("float");
        reserved.add("for");reserved.add("if");reserved.add("goto");
        reserved.add("implements");reserved.add("import");reserved.add("instanceof");
        reserved.add("int");reserved.add("interface");reserved.add("long");
        reserved.add("native");reserved.add("new");reserved.add("null");
        reserved.add("package");reserved.add("private");reserved.add("protected");
        reserved.add("public");reserved.add("return");reserved.add("short");
        reserved.add("static");reserved.add("strictfp");reserved.add("super");
        reserved.add("switch");reserved.add("synchronized");reserved.add("this");
        reserved.add("throw");reserved.add("throws");reserved.add("transient");
        reserved.add("true");reserved.add("try");reserved.add("void");
        reserved.add("volatile");reserved.add("while");
    

    /**
     * Checks if the string that is provided is a valid Java package name (contains only
     * [a-z,A-Z,_,$], every element is separated by a single '.' , an element can't be one of Java's
     * reserved words.
     *
     * @param name The package name that needs to be validated.
     * @return <b>true</b> if the package name is valid, <b>false</b> if its not valid.
     */
    public static final boolean isValidPackageName(String name) 
        String[] parts=name.split("\\.",-1);
        for (String part:parts)
            System.out.println(part);
            if (reserved.contains(part)) return false;
            if (!validPart(part)) return false;
        
        return true;
    

    /**
     * Checks that a part (a word between dots) is a valid part to be used in a Java package name.
     * @param part The part between dots (e.g. *PART*.*PART*.*PART*.*PART*).
     * @return <b>true</b> if the part is valid, <b>false</b> if its not valid.
     */
    private static boolean validPart(String part)
        if (part==null || part.length()<1)
            // Package part is null or empty !
            return false;
        
        if (Character.isJavaIdentifierStart(part.charAt(0)))
            for (int i = 0; i < part.length(); i++)
                char c = part.charAt(i);
                if (!Character.isJavaIdentifierPart(c))
                    // Package part contains invalid JavaIdentifier !
                    return false;
                
            
        else
            // Package part does not begin with a valid JavaIdentifier !
            return false;
        

        return true;
    

【讨论】:

【参考方案6】:

工作正则表达式的较短版本:

\pAlnum[\pAlnum._]+\pAlnum

【讨论】:

【参考方案7】:

对于像 com.mycompany.core.functions.CustomFunction 这样的字符串,我使用的是((?:(?:\w+)?\.[a-z_A-Z]\w+)+)

【讨论】:

【参考方案8】:

以下表达式对我来说非常有效。

^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+$

【讨论】:

区分大小写很重要【参考方案9】:

我会说类似([\w]+\.)*[\w]+

但也许我可以更具体地知道你想用它做什么;)

【讨论】:

你不需要[],这应该足够了(\\w+\\.?)+ 我认为 [] 让事情变得更清晰,正则表达式已经够乱了 ;) 我让最后一点在外面清楚地将包与类名分开。 我想看看给定的输入是否是一个好的java类名(完全限定包),使用hibernate验证器(通过@Pattern的注释样式)。

以上是关于正则表达式(全)的主要内容,如果未能解决你的问题,请参考以下文章

Linux Bash之正则表达式

linux shell:bash 正则表达式判断操作符 =~ 的问题

Bash 脚本:正则表达式基础篇 | Linux 中国

使用 linux 和 AIX 的正则表达式替换 bash 脚本中的字符串

Linux 第17天 bash,find,正则,命令历史

linux学习第4天(自习)