如何使用sed匹配2或3个冒号?

时间:2015-12-19 19:48:23

标签: regex sed matching regex-group

我正在玩正则表达式组织,并且遇到困扰我的事情。鉴于以下内容:

TestEko:::Test
TestEko::Test

我无法匹配冒号组。我尝试了以下内容:

\(::\|:::\)  # only matches ::
\(:\{2,3\}\) # only matches ::
\(::\+\)     # only matches ::

那么,我如何匹配第一行的:::和第二行的::

3 个答案:

答案 0 :(得分:0)

如果您想匹配任意数量的冒号,请尝试使用以下表达式

s/(:)+/*/g

这会将任意数量的冒号替换为*

您的输出将是

TestEko* Test
TestEko* Test

答案 1 :(得分:0)

这可能适合你(GNU sed):

sed 's/:::\?/X&X/' file # should print TestEkoX:::XTest and TestEkoX::XTest

答案 2 :(得分:0)

每个工具处理正则表达式的方式略有不同。甚至sed也有不同的方式,因为有多种sed实现。

如果您使用的是Linux,那么您可能正在运行GNU sed,它可以随心所欲地完成您的工作:

$ printf 'one::two\nthree:::four\n' | sed 's/:::\?/_/'
one_two
three_Four

然而,在FreeBSD中,你使用的是BSD sed,它与GNU的工作方式不同。在FreeBSD中,以下工作(类似于你的一次尝试):

$ printf 'one::two\nthree:::four\n' | sed 's/:\{2,3\}/_/'
one_two
three_four

当然,如果您使用Extended RE而不是sed的默认Basic RE表示法,所有这些都会被简化。 (您可以man re_format了解有关此内容的更多信息。)

在Linux和FreeBSD中,这有效:

$ printf 'one::two\nthree:::four\n' | sed -r 's/:::?/_/'
one_two
three_four

在FreeBSD和OSX中,这有效:

$ printf 'one::two\nthree:::four\n' | sed -E 's/:::?/_/'
one_two
three_four

是的,FreeBSD支持扩展RE的-r-E-E选项是在几年前引入的,OSX使用BSD源代码作为自己的版本。为了与GNU sed兼容,FreeBSD的后续版本添加了-r,但OSX尚未采用该版本。

当然,我应该指出,所有这些都受到影响,因为它们并非固定在任何一方的非冒号字符上。从技术上讲,如果您只搜索::,则还会匹配:::

printf 'one::two\nthree:::four\n' | sed -r 's/::/_/'
one_two
three_:four

所以你需要一些方法来识别“非冒号”字符。你不能使用单词分隔符([[:<:]][[:>:]]),因为这不是单词边界,但这应该有效:

$ printf 'one::two\nthree:::four\nfive::::six\n' | sed -r 's/([^:])(:::?)([^:])/\1_\3/'
one_two
three_four
five::::six

即使在BRE中:

printf 'one::two\nthree:::four\nfive::::six\n' | sed 's/\([^:]\):\{2,3\}\([^:]\)/\1_\2/'
one_two
three_four
five::::six  

这有帮助吗?