我已經看到了這個例子:搜索和在bash替換使用正則表達式
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}
哪些語法如下:${variable//pattern/replacement}
不幸的是,pattern
領域似乎並不支持完整的regex語法(如我使用.
或\s
,例如,它試圖匹配文字字符)。
如何使用完整正則表達式語法搜索/替換字符串?
我已經看到了這個例子:搜索和在bash替換使用正則表達式
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}
哪些語法如下:${variable//pattern/replacement}
不幸的是,pattern
領域似乎並不支持完整的regex語法(如我使用.
或\s
,例如,它試圖匹配文字字符)。
如何使用完整正則表達式語法搜索/替換字符串?
使用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'
這可以讓你做更多的創意匹配...例如,在剪斷上述情況,除非第一個表達式匹配,否則不會使用數字替換(由於惰性and
評估)。當然,你有充分的語言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想知道什麼豪ver,如果我正確地理解了這個問題,爲什麼「完整」或PCRE擴展\s\S\w\W\d\D
等不能像php ruby python等支持的那樣工作。這些擴展是來自Perl兼容的正則表達式(PCRE),可能不兼容其他形式的基於shell的正則表達式。
這些不工作:
所有文字 「d」 字#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//\d/}
#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello | sed 's/\d//g'
輸出取出
ho02123ware38384you44334o3434ingto38384ay
但下面確實如預期工作
#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello | perl -pe 's/\d//g'
輸出
howareyoudoingtodday
。希望澄清的東西多一點,但如果你不感到困惑,爲什麼不試試這個Mac OS X上它啓用了REG_ENHANCED標誌:
#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day;
echo $MYVAR | grep -o -E '\d'
在* nix你會的最口味僅看到以下輸出:
d
d
d
nJoy!
請原諒? '$ {foo // $ bar/$ baz}'是**不是** POSIX.2 BRE或ERE語法 - 它是fnmatch()風格的模式匹配。 –
...所以,如果我們只想過濾出以字母「o」開頭的數字,那麼'$ {hello // [[:digit:]] /}'可行,'$ {hello // o [[ :digit:]] *}'會有一個完全不同的行爲,因爲在fnmatch模式中,'*'匹配所有字符,而不是修改之前的項目爲0或更多)。 –
有關fnmatch的完整規範,請參閱http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13_03(以及它通過引用合併的所有內容)。 –
這實際上可以以純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]
找到一個相關的問題在這裏:http://stackoverflow.com/questions/5658085/bash-script-regular-expressions-how-to-find-and-replace-all-matches – jheddings
僅供參考,'\ s'不是標準POSIX定義的正則表達式語法(BRE或ERE)的一部分;這是一個PCRE擴展,並且大部分不可用於shell。 '[[:space:]]'是更通用的等價物。 –
'\ s'可以用'[[:space:]]'替換,'''用'''替換',基線shell模式語言的extglob擴展可以用於像可選子組這樣的事物,重複團體等。 –