我有一个非常简单的awk脚本,需要查看一个字符串并替换双美元符号($$)的任何实例,双美元符号中间的数字($ 123 $)和单一美元符号($)用和_。我用gsub在两个正则表达式中很容易做到,但我觉得我应该能够用一个正则表达式做它并且让我疯狂,我无法锁定它。可能无关紧要的时间或速度,但在这一点上,我只需要知道我是否正确有一种更浓缩的方式或者我是否疯了。
以下是我目前的情况:
gsub (/\$[0-9]*\$/, "_", $1);
gsub (/\$/, "_", $1);
我认为使用
在一行中设置它没有问题gsub (/\$[0-9]*\$*/, "_", $1);
但是我没有意识到有一个单一美元符号跟随数字($ 123)的情况,我只想替换美元符号而不是数字。所以我需要匹配1美元符号,然后是0或更多数字,如果数字匹配则需要1美元符号,或者如果没有数字则匹配0到1(或更多,并不重要)美元符号。
编辑:对不起,我没有给出输入和所需输出的更好示例。
输入:
foo$bar$$foofoo$353$foobar$123
abc$123$xyz$$123abc$def$$hij$456$klm
输出:
foo_bar_foofoo_foobar_123
abc_xyz_123abc_def_hij_klm
希望我想要的更清楚。
答案 0 :(得分:2)
您的要求不是很清楚,但这是您想要的吗?
$ awk '{sub(/\$([0-9]*\$)*/,"_")}1' file
_ - match
_ - match
_ - match
_123 - don't match
IDK,如果以上是预期的输出,或者没有给出我假设的是您发布的样本输入:
$ cat file
$ - match
$$ - match
$124$ - match
$123 - don't match
答案 1 :(得分:1)
我认为awk
在正则表达式中支持负向前瞻,所以你需要使用程序逻辑。
gsub(/\$[0-9]*\$/, "_", $1);
if ($1 ~ /\$/ && $1 !~ /\$[0-9]/) gsub(/\$/, "_", $1);
但是,这不会使用$foo $123
之类的字符串,因为$123
会阻止任何替换。
如果您正在使用GNU Awk,则可以使用其gensub
函数在替换中使用捕获组。然后,您可以匹配$
后跟不是数字的内容,并将非数字复制到替换中。
gensub(/\$([^0-9]|$)/, "_\\1", "g", $1);