Bash字符串处理(与Java对照) - 21.字符串正则匹配
Bash字符串处理(与Java对照) - 21.字符串正则匹配
In Java
正则表达式查询
String.matches方法
boolean matches(String regex)
通知此字符串是否匹配给定的正则表达式。
String str = "123456"; String re = "\\d+"; if (str.matches(re)) { // do something }
Pattern类和Matcher类
String str = "abc efg ABC"; String re = "a|f"; //表示a或f Pattern p = Pattern.compile(re); Matcher m = p.matcher(str); boolean rs = m.find();
如果str中有re,那么rs为true,否则为flase。如果想在查找时忽略大小写,则可以写成Pattern p = Pattern.compile(re, Pattern.CASE_INSENSITIVE);
正则表达式提取
String re = ".+\\(.+)$"; String str = "c:\\dir1\\dir2\\name.txt"; Pattern p = Pattern.compile(re); Matcher m = p.matcher(str); boolean rs = m.find(); for (int i = 1; i <= m.groupCount(); i++) { System.out.println(m.group(i)); }
以上的执行结果为name.txt,提取的字符串储存在m.group(i)中,其中i最大值为m.groupCount();
正则表达式分割
String re = "::"; Pattern p = Pattern.compile(re); String[] r = p.split("xd::abc::cde");
执行后,r就是{"xd","abc","cde"},其实分割时还有跟简单的方法:
String str="xd::abc::cde"; String[] r = str.split("::");
正则表达式替换(删除)
String re = "a+"; //表示一个或多个a Pattern p = Pattern.compile(re); Matcher m = p.matcher("aaabbced a ccdeaa"); String s = m.replaceAll("A");
结果为"Abbced A ccdeA"
如果写成空串,既可达到删除的功能,比如:String re = "a+"; //表示一个或多个a Pattern p = Pattern.compile(re); Matcher m = p.matcher("aaabbced a ccdeaa"); String s = m.replaceAll("");
结果为"bbced ccde"
String.replaceAll 和 String.replaceFirst 是可执行正则表达式替换(删除)的简易做法。但String.replace不是按正则表达式来进行的。
ReturnsanewstringresultingfromreplacingalloccurrencesofoldCharinthisstringwithnewChar.
Stringreplace(CharSequencetarget,CharSequencereplacement)
Replaceseachsubstringofthisstringthatmatchestheliteraltargetsequencewiththespecifiedliteralreplacementsequence.
StringreplaceAll(Stringregex,Stringreplacement)
Replaceseachsubstringofthisstringthatmatchesthegivenregularexpressionwiththegivenreplacement.
StringreplaceFirst(Stringregex,Stringreplacement)
Replaces the first substring of this string that matches the given regular expression with the given replacement.Java中常用的正则表达式元字符
. 代表任意字符
?表示前面的字符出现0次或1次
+表示前面的字符出现1次或多次
*表示前面的字符出现0次或多次
{n}表示前面的字符出现正好n次
{n,}表示前面的字符出现n次或以上
{n,m}表示前面的字符出现n次到m次
\d等于[0-9]数字
\D等于[^0-9]非数字
\s等于[\t\n\x0B\f]空白字元
\S等于[^\t\n\x0B\f]非空白字元
\w等于[a-zA-Z_0-9]数字或是英文字
\W等于[^a-zA-Z_0-9]非数字与英文字
^ 表示每行的开头$ 表示每行的结尾
In Bash
Bash对正则表达式的支持
Bash v3 内置对正则表达式匹配的支持,操作符为 =~。(Bash Version 3)
[[ "$STR" =~ "$REGEX" ]]
Anadditionalbinaryoperator,=~,isavailable,withthesameprecedenceas==and!=.Whenitis
used,thestringtotherightoftheoperatorisconsideredanextendedregularexpressionandmatched
accordingly(asinregex(3)).Thereturnvalueis0ifthestringmatchesthepattern,and1otherwise.
Iftheregularexpressionissyntacticallyincorrect,theconditionalexpression’sreturnvalueis2.
Iftheshelloptionnocasematchisenabled,thematchisperformedwithoutregardtothecaseofalpha-
beticcharacters.Substringsmatchedbyparenthesizedsubexpressionswithintheregularexpressionare
savedinthearrayvariableBASH_REMATCH.TheelementofBASH_REMATCHwithindex0istheportionof
thestringmatchingtheentireregularexpression.TheelementofBASH_REMATCHwithindexnisthepor-
tion of the string matching the nth parenthesized subexpression.在Bash中二元操作符 =~ 进行扩展的正则表达式匹配。如果匹配,返回值为0,否则1,如果正则表达式错误,返回2。如果shell选项nocasematch没有开启,那么匹配时区分大小写。在正则表达式中小括号包围的子表达式的匹配结果保存在BASH_REMATCH中,它是个数组,${BASH_REMATCH[0]}是匹配的整个字符串,${BASH_REMATCH[1]}是匹配的第一个子表达式的字符串,其他以此类推。
以下脚本来自 http://www.linuxjournal.com/content/bash-regular-expressions 很好的展示了Bash3.0中内置的正则表达式匹配功能。
#!/bin/bash if [[ $# -lt 2 ]]; then echo "Usage: $0 PATTERN STRINGS..." exit 1 fi regex=$1 shift echo "regex: $regex" echo while [[ $1 ]] do if [[ $1 =~ $regex ]]; then echo "$1 matches" i=1 n=${#BASH_REMATCH[*]} while [[ $i -lt $n ]] do echo " capture[$i]: ${BASH_REMATCH[$i]}" let i++ done else echo "$1 does not match" fi shift done
[root@jfht ~]# ./bashre.sh 'aa(b{2,3}[xyz])cc' aabbxcc aabbcc
regex:aa(b{2,3}[xyz])cc
aabbxccmatches
capture[1]:bbx
aabbccdoesnotmatch
[root@jfht ~]#在grep/egrep命令中进行正则表达式匹配
使用Basic RE
格式1:echo "$STR" | grep -q "$REGEX"
格式2:grep -q "$REGEX" <<<"$STR"
使用Extended RE
格式3:echo "$STR" | egrep -q "$REGEX"
格式4:egrep -q "$REGEX" <<<"$STR"
注意:grep/egrep加上-q参数是为了减少输出,根据退出码判断是否匹配,退出码为0时表示匹配。
-E,--extended-regexp
InterpretPATTERNasanextendedregularexpression(seebelow).
-ePATTERN,--regexp=PATTERN
UsePATTERNasthepattern;usefultoprotectpatternsbeginningwith-.
-q,--quiet,--silent
Quiet;donotwriteanythingtostandardoutput.Exitimmediatelywithzerostatusifanymatchis
found, even if an error was detected. Also see the -s or --no-messages option.匹配手机号码,模式为:1[3458][0-9]{9} 或 1[3458][0-9]\{9\}
[root@jfht ~]# echo "13012345678" | egrep '1[3458][0-9]{9}'
13012345678
[root@jfht~]#echo"13012345678"|grep'1[3458][0-9]{9}'
[root@jfht~]#echo"13012345678"|grep'1[3458][0-9]\{9\}'
13012345678
[root@jfht ~]#STR="13024184301" REGEX="1[3458][0-9]{9}" if echo "$STR" | egrep -q "$REGEX"; then echo "matched" else echo "not matched" fi
[root@jfht ~]# STR="13024184301"
[root@jfht~]#REGEX="1[3458][0-9]{9}"
[root@jfht~]#ifecho"$STR"|egrep-q"$REGEX";then
>echo"matched"
>else
>echo"notmatched"
>fi
matched
[root@jfht ~]#使用expr match进行正则表达式匹配
expr match "$STR" "$REGEX"
expr "$STR" : "$REGEX"
打印与正则表达式匹配的长度。
anchoredpatternmatchofREGEXPinSTRING
matchSTRINGREGEXP
same as STRING : REGEXP[root@jfht ~]# STR=Hello
[root@jfht~]#REGEX=He
[root@jfht~]#expr"$STR":"$REGEX"
2[root@jfht ~]# REGEX=".*[aeiou]"
[root@jfht~]#expr"$STR":"$REGEX"
5注意:贪婪匹配!
[root@jfht ~]# REGEX=ll
[root@jfht~]#expr"$STR":"$REGEX"
0另外,expr match 也可以实现根据正则表达式取子串。
expr match "$STR" ".*\($SUB\).*"
expr "$STR" : ".*\($SUB\).*"
注意与上面不同的是,结果是子串,而不是匹配的长度。
[root@jfht ~]# STR="某某是2009年进公司的"
想从此字符串中提取出数字来,下面是尝试的过程。
[root@jfht~]#SUB="[0-9]+"
[root@jfht~]#expr"$STR":".*\($SUB\).*"
[root@jfht~]#SUB="[0-9]\+"
[root@jfht~]#expr"$STR":".*\($SUB\).*"
9
[root@jfht~]#SUB="[0-9]*"
[root@jfht~]#expr"$STR":".*\($SUB\).*"
[root@jfht~]#SUB="[0-9]\*"
[root@jfht ~]# expr "$STR" : ".*\($SUB\).*"上面的写法都无法做到提取完整的年份,因为在正则匹配的时候是贪婪匹配,前面.*已经把能匹配的全部吃掉了。
[root@jfht~]#expr"$STR":"[^0-9]*\([0-9]\+\).*"
2009网上问题:形如"someletters_12345_moreleters.ext"的文件名,以一些字母开头、跟上下划线、跟上5个数字、再跟上下划线、以一些字母及扩展名结尾。现在需要将数字提取出来,保存到一个变量中。
[root@jfht ~]# echo someletters_12345_moreleters.ext | cut -d'_' -f 212345
[root@jfht ~]# expr match 'someletters_12345_moreleters.ext' '.\+_\(.\+\)_.*'12345
[root@jfht ~]# FILE=someletters_12345_moreleters.ext
[root@jfht~]#NUM=$(exprmatch"$FILE"'.\+_\(.\+\)_.*')
[root@jfht~]#echo$NUM
12345返回目录:Java程序员的Bash实用指南系列之字符串处理(目录)
上节内容:Bash字符串处理(与Java对照) - 20.查找子串的位置
下节内容:Bash字符串处理(与Java对照) - 22.判断字符串是否数字串