使用sed的正则表达式分组替换字符

时间:2011-03-14 22:37:13

标签: regex sed grouping backreference

我有一个像这样的文本文件:

FOO BAR PIPPO PLUTO 31337 1010
FOOZ BAZ 130
VERY LONG LINE LIKE THIS THEN A NUMBER LIKE 42

我需要把它变成:

FOO-BAR-PIPPO-PLUTO 31337 1010
FOOZ-BAZ 130
VERY-LONG-LINE-LIKE-THIS-THEN-A-NUMBER-LIKE 42

我能做的最好的事情是:

sed -re 's/([A-Z]+)( )([A-Z]+)/\1-\3/g'

但输出是

FOO-BAR PIPPO-PLUTO 31337 1010
FOOZ-BAZ 130
VERY-LONG LINE-LIKE THIS-THEN A-NUMBER LIKE 42

关闭,但没有雪茄。关于为什么我的正则表达式不起作用的任何想法?

3 个答案:

答案 0 :(得分:4)

你不能有重叠的比赛。未检测到“BAR PIPPO”,因为匹配“FOO BAR”时已经消耗了“BAR”。

FOO BAR PIPPO PLUTO 31337 1010
------- ===========
   1         2

请改为尝试:

$ sed -re 's/ ([A-Z])/-\1/g'

请注意,这没有重叠匹配:

FOO BAR PIPPO PLUTO 31337 1010
   --  ==    --
   1   2     3

答案 1 :(得分:1)

sed 's/ \([^0-9]\)/-\1/g'

只需查找空格,然后找不到数字,并用-替换该空格。这样做的好处是它适用于具有非字母数字字符的行。

概念证明

$ cat ./infile
FOO BAR PIPPO PLUTO 31337 1010
FOOZ BAZ 130
VERY LONG LINE LIKE THIS THEN A NUMBER LIKE 42
THIS LINE HAS $ODD$ #CHARS# IN %IT% 42

$ sed 's/ \([^0-9]\)/-\1/g' ./infile
FOO-BAR-PIPPO-PLUTO 31337 1010
FOOZ-BAZ 130
VERY-LONG-LINE-LIKE-THIS-THEN-A-NUMBER-LIKE 42
THIS-LINE-HAS-$ODD$-#CHARS#-IN-%IT% 42

答案 2 :(得分:0)

非常接近。你不需要匹配多个字母 - 你只需要字母空格字母:

sed -Ee 's/([A-Z])( )([A-Z])/\1-\3/g' foo.txt 
FOO-BAR-PIPPO-PLUTO 31337 1010
FOOZ-BAZ 130
VERY-LONG-LINE-LIKE-THIS-THEN-A NUMBER-LIKE 42

(根据BSD sed调整sed params)