使用awk gsub或通用正则表达式替换匹配本身,而不是通配符

Vin*_*fer 1 regex awk replace find gsub

我有以下外观的制表符分隔文件:

12-38070040-39070040    13-92416321-93446176    14-47539055-48560868     14-89244697-90244697   14-90046821-91047886    14-98556636-99556636    15-47718221-48718221    
Run Code Online (Sandbox Code Playgroud)

我想替换所有的实例:

选项卡,然后任意两位数,然后是连字符\ t [0-9] [0-9] -

有:

选项卡,然后相同的两个数字,然后冒号\ t相同的两个数字:

12:38070040-39070040    13:92416321-93446176    14:47539055-48560868     14:89244697-90244697   14:90046821-91047886    14:98556636-99556636    15:47718221-48718221    
Run Code Online (Sandbox Code Playgroud)

如何使用通配符进行匹配,然后替换匹配,而不是替换通配符?

最后一点,我已经问过,awk '{gsub()}'因为我使用它最多,但是如果有通用的"伪正则表达"可以在大多数环境,大多数文本编辑器等工作,我会很高兴了解到这一点.

Tom*_*ech 5

听起来你所指的是一个捕获组.捕获组使您可以在替换字符串中使用匹配模式的一部分.

Normal gsub不允许您使用捕获组,但如果您使用的是GNU awk,则可以使用gensub:

awk '{print gensub(/\y([0-9][0-9])-/, "\\1:", "g")}' file
Run Code Online (Sandbox Code Playgroud)

这将捕获前面带有单词边界的两个数字\y,后跟一个连字符.然后在替换中使用这些数字(这就是\\1它的用途),然后是冒号."g"参数表示执行全局替换.如果指定了多个捕获组,它们将是\\2,\\3等等.

在您的文件上测试它:

$ awk '{print gensub(/\y([0-9][0-9])-/, "\\1:", "g")}' file
12:38070040-39070040    13:92416321-93446176    14:47539055-48560868     14:89244697-90244697   14:90046821-91047886    14:98556636-99556636    15:47718221-48718221
Run Code Online (Sandbox Code Playgroud)

你可以使用sed做同样的工作:

sed -r 's/(^|[[:space:]])([0-9]{2})-/\1\2:/g' file
Run Code Online (Sandbox Code Playgroud)

这匹配任何两个数字,前面是空格类中的字符(包括制表符和空格)或行的开头,^后跟连字符.现在有两个捕获组,因此替换包含它们以及冒号.使用BSD sed(例如在Mac上),使用-E而不是-r启用扩展正则表达式模式.

由于我们正在处理正则表达式,所以不提Perl似乎是不合理的:

perl -pe 's/\b(\d{2})-/\1:/g' file
Run Code Online (Sandbox Code Playgroud)

这使用了\b与数字的开头和行的开头或空格之间的间隙匹配的单词boundary .\d是数字类,是简写[0-9].替换类似于awk中的替换,除了我们不需要逃避反斜杠.

所有情况下的输出:

12:38070040-39070040    13:92416321-93446176    14:47539055-48560868     14:89244697-90244697   14:90046821-91047886    14:98556636-99556636    15:47718221-48718221
Run Code Online (Sandbox Code Playgroud)