我试图使用 awk 将第一个字段中最后出现的句点替换为分号。字段分隔符也是分号。
我(\.)(?!.*\1)
在 regex101.com 上作为正则表达式进行了测试,当我提供“abcmp3”作为输入时,它正确地突出显示了最后一次出现的句点。
我在 awk 中尝试过以下操作:
awk 'BEGIN{FS=OFS=";"} {gsub(/(\.)(?!.*\1)/, ";", $1)} 1'
它不能取代任何东西。
我将不胜感激任何能对此提供帮助的人。
答案1
AFAIK,没有 awk 的实现支持 PCRE 环视,例如(?!re)
.
在 GNU awk(又名 gawk)中,使用根子函数,您可以贪婪地捕获句号之前的所有内容,并在替换中将其反向替换:
$ echo 'foo.bar.baz;something;else' |
gawk 'BEGIN{OFS=FS=";"} {$1 = gensub(/(.*)\./,"\\1;","1",$1)} 1'
foo.bar;baz;something;else
可移植的是,您可以使用匹配函数,再次进行贪心匹配,然后选出句号之前和之后的子字符串:
$ echo 'foo.bar.baz;something;else' |
mawk 'BEGIN{OFS=FS=";"} match($1,/.*\./){$1 = substr($1,1,RLENGTH-1) ";" substr($1,RLENGTH+1)} 1'
foo.bar;baz;something;else
使用 GNU awk,您可以(同样不可移植)match
通过其可选的数组参数使用捕获和反向替换:
$ echo 'foo.bar.baz;something;else' |
gawk 'BEGIN{OFS=FS=";"} match($1,/(.*)\.(.*)/,a){$1 = a[1] ";" a[2]} 1'
foo.bar;baz;something;else
由于lookahead与perl兼容,您当然可以使用perl(尽管可能没有捕获和反向引用\.
,这在任何情况下都显得有些过分):
$ echo 'foo.bar.baz;something;else' |
perl -F';' -pe '$_ = join ";", $F[0] =~ s/\.(?!.*\.)/;/r, @F[1..$#F]'
foo.bar;baz;something;else
磨坊主与 awk 类似,sub
并且gsub
像 GNU awk 一样gensub
,支持捕获和反向引用:
$ echo 'foo.bar.baz;something;else' |
mlr --nidx --fs ';' put '$1 = sub($1,"(.*)\.","\1;")'
foo.bar;baz;something;else
据我所知,它目前不支持环视。
答案2
怎么样sed
?就您而言,您很幸运能够在领域 1 工作:
sed 's/\.\([^.]*;\)/;\1/'