带有可选小数点和反向引用的sed数字

时间:2018-12-14 17:14:54

标签: sed

我有这样简单的输入:

11111(n)
222222(p)
33333333(:)

我可以使用sed后向引用将括号替换为这样的数字:

sed -e 's/\([[:digit:]]*\)\((.*)\)/\2 \1/' file

产生

(n) 11111
(p) 222222
(:) 33333333

太酷了!

但是像这样可能的十进制数字使事情变得更加困难

11111(n)
11111.111(n)
2222222.22(p)
33.3333333(:)

我尝试了很多命令,例如

sed -e 's/\([[:digit:]]*(\.[[:digit:]]*?)\)\((.*)\)/\2 \1/' file
sed -e 's/\([[:digit:]]*\.?[[:digit:]]*?)\)\((.*)\)/\2 \1/' file
sed -e 's/\([[:digit:]]*\.*[[:digit:]]*)\)\((.*)\)/\2 \1/' file
sed -e 's/\([[:digit:]]*.*[[:digit:]]*)\)\((.*)\)/\2 \1/' file

需要的输出:

(n) 11111
(n) 11111.111
(p) 2222222.22
(:) 33.3333333

请注意,数字可以是任意长(1到n位数字),十进制标记(。)和十进制数字是可选的。

此外,sed似乎没有stackexchange所指出的\d速记

3 个答案:

答案 0 :(得分:1)

您可以使用此sed

sed -E 's/^([.[:digit:]]+)(\([^)]*\))/\2 \1/g' file

(n) 11111
(n) 11111.111
(p) 2222222.22
(:) 33.3333333

此处[.[:digit:]]+将匹配1+的任何数字或点字符。

答案 1 :(得分:1)

当您知道与[:digit:]匹配的POSIX括号表达式中的内容时,它将变得非常简单。您需要做的就是添加另一个.,以便括号表达式将表示数字集以及.

sed 's/\([[:digit:].]*\)\((.*)\)/\2 \1/' file

您也无需提及-e,因为默认情况下,sed在BRE(基本正则表达式)模式下运行,而在-E下,ERE(扩展正则表达式)模式为已启用。 \d也不是sed的任何版本(POSIX,GNU或FreeBSD)用来匹配数字的有效正则表达式构造。我想它在PCRE库中受支持,您可以在其中使用perl

perl -lne 'print "$2 $1" if /(\d+\.?\d*).*(\([^)]*\))/' file

答案 2 :(得分:0)

为什么不只使用简单集合?

sed -e 's/\([0-9.]*\)\((.*)\)/\2 \1/' file

由于[0-9]和[:digit:] 基本相同,但是当您要包含其他字符时,前一个字符会更直观。

再想一想,我发现您正在尝试匹配合法数字,即没有分数或只有分数,因此改进的sed将是:

sed -r 's/([0-9]+(\.[0-9]+)?)(\(.*\))/\3 \1/' file

-r是否支持+?在RE中并切换括号的转义。
或使用perl避免所有这些RE扩展名混淆:

perl -lne 'print "$3 $1" if /(\d+(\.\d+)?)\s*(\(.*?\))/' file

更新: 正如本杰明·W。在评论中提到的,[0-9]和[[:digit:]]不相同,因此,如果要考虑其他语言中可能的数字,sed应该是:

sed -r 's/([[:digit:]]+(\.[[:digit:]]+)?)(\(.*\))/\3 \1/' file