我看过这个例子:
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}
遵循以下语法:${variable//pattern/replacement}
不幸的是,模式字段似乎不支持完整的正则表达式语法(如果我使用。或者\s,例如,它试图匹配文字字符)。
我如何使用完整的正则表达式语法搜索/替换字符串?
我看过这个例子:
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}
遵循以下语法:${variable//pattern/replacement}
不幸的是,模式字段似乎不支持完整的正则表达式语法(如果我使用。或者\s,例如,它试图匹配文字字符)。
我如何使用完整的正则表达式语法搜索/替换字符串?
当前回答
这实际上可以在纯bash中完成:
hello=ho02123ware38384you443d34o3434ingtod38384day
re='(.*)[0-9]+(.*)'
while [[ $hello =~ $re ]]; do
hello=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
done
echo "$hello"
收益率…
howareyoudoingtodday
其他回答
使用sed:
MYVAR=ho02123ware38384you443d34o3434ingtod38384day
echo "$MYVAR" | sed -e 's/[a-zA-Z]/X/g' -e 's/[0-9]/N/g'
# prints XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX
注意,后面的-e是按顺序处理的。此外,表达式的g标志将匹配输入中出现的所有情况。
你也可以使用这个方法选择你最喜欢的工具,例如perl, awk,例如:
echo "$MYVAR" | perl -pe 's/[a-zA-Z]/X/g and s/[0-9]/N/g'
这可以让你做出更有创意的搭配……例如,在上面的片段中,除非在第一个表达式上有匹配,否则不会使用数字替换(由于延迟和求值)。当然,您有Perl的完整语言支持来执行您的命令……
这些例子也可以在bash中工作,不需要使用sed:
#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day
MYVAR=${MYVAR//[a-zA-Z]/X}
echo ${MYVAR//[0-9]/N}
也可以使用字符类括号表达式
#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day
MYVAR=${MYVAR//[[:alpha:]]/X}
echo ${MYVAR//[[:digit:]]/N}
输出
XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX
然而,@Lanaru想知道的是,如果我理解正确的话,为什么“完整”或PCRE扩展\s\ s\ w\ w\ d\ d等不像php、ruby、python等所支持的那样工作。这些扩展来自与perl兼容的正则表达式(PCRE),可能与其他形式的基于shell的正则表达式不兼容。
这些都不管用:
#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//\d/}
#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello | sed 's/\d//g'
输出时删除所有“d”字面值
ho02123ware38384you44334o3434ingto38384ay
但下面的操作确实如预期的那样工作
#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello | perl -pe 's/\d//g'
输出
howareyoudoingtodday
希望这能更清楚地说明问题,但如果你还不困惑,为什么不在启用了REG_ENHANCED标志的Mac OS X上尝试一下:
#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day;
echo $MYVAR | grep -o -E '\d'
在大多数*nix版本中,你只会看到以下输出:
d
d
d
nJoy !
这实际上可以在纯bash中完成:
hello=ho02123ware38384you443d34o3434ingtod38384day
re='(.*)[0-9]+(.*)'
while [[ $hello =~ $re ]]; do
hello=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
done
echo "$hello"
收益率…
howareyoudoingtodday
使用[[:digit:]](注意双括号)作为模式:
$ hello=ho02123ware38384you443d34o3434ingtod38384day
$ echo ${hello//[[:digit:]]/}
howareyoudoingtodday
只是想总结一下答案(尤其是@nickl-的https://stackoverflow.com/a/22261334/2916086)。
如果您正在重复调用并且关心性能,这个测试显示BASH方法比分支到sed和可能的任何其他外部进程快15倍。
hello=123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X
P1=$(date +%s)
for i in {1..10000}
do
echo $hello | sed s/X//g > /dev/null
done
P2=$(date +%s)
echo $[$P2-$P1]
for i in {1..10000}
do
echo ${hello//X/} > /dev/null
done
P3=$(date +%s)
echo $[$P3-$P2]