我看过这个例子:

hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}

遵循以下语法:${variable//pattern/replacement}

不幸的是,模式字段似乎不支持完整的正则表达式语法(如果我使用。或者\s,例如,它试图匹配文字字符)。

我如何使用完整的正则表达式语法搜索/替换字符串?


当前回答

这些例子也可以在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)。

你可以使用python。这样做效率不高,但可以使用更灵活的语法完成工作。

申请存档

下面的pythonscript将“FROM”(而不是“notFrom”)替换为“TO”。

regex_replace.py

import sys
import re

for line in sys.stdin:
    line = re.sub(r'(?<!not)FROM', 'TO', line)
    sys.stdout.write(line)

你可以把它应用在文本文件上,比如

$ cat test.txt
bla notFROM
FROM FROM
bla bla
FROM bla

bla  notFROM FROM

bla FROM
bla bla


$ cat test.txt | python regex_replace.py
bla notFROM
TO TO
bla bla
TO bla

bla  notFROM TO

bla TO
bla bla

应用于变量

#!/bin/bash

hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello

PYTHON_CODE=$(cat <<END
import sys
import re

for line in sys.stdin:
    line = re.sub(r'[0-9]', '', line)
    sys.stdout.write(line)
END
)
echo $hello | python -c "$PYTHON_CODE"

输出

ho02123ware38384you443d34o3434ingtod38384day
howareyoudoingtodday

设置var

hello=ho02123ware38384you443d34o3434ingtod38384day

然后,在var上用regex替换echo

echo ${hello//[[:digit:]]/}

这将打印:

howareyoudoingtodday

额外-如果你想要相反的(获得数字字符)

echo ${hello//[![:digit:]]/}

这将打印:

021233838444334343438384

这个例子在输入hello ugly世界中搜索正则表达式bad|ugly并将其替换为nice

#!/bin/bash

# THIS FUNCTION NEEDS THREE PARAMETERS
# arg1 = input              Example:  hello ugly world
# arg2 = search regex       Example:  bad|ugly
# arg3 = replace            Example:  nice
function regex_replace()
{
  # $1 = hello ugly world
  # $2 = bad|ugly
  # $3 = nice

  # REGEX
  re="(.*?)($2)(.*)"

  if [[ $1 =~ $re ]]; then
    # if there is a match
    
    # ${BASH_REMATCH[0]} = hello ugly world
    # ${BASH_REMATCH[1]} = hello 
    # ${BASH_REMATCH[2]} = ugly
    # ${BASH_REMATCH[3]} = world    

    # hello + nice + world
    echo ${BASH_REMATCH[1]}$3${BASH_REMATCH[3]}
  else    
    # if no match return original input  hello ugly world
    echo "$1"
  fi    
}

# prints 'hello nice world'
regex_replace 'hello ugly world' 'bad|ugly' 'nice'

# to save output to a variable
x=$(regex_replace 'hello ugly world' 'bad|ugly' 'nice')
echo "output of replacement is: $x"
exit