重复第 n 个数字直到第 n 个匹配,同时使用 awk sub 在模式中为这些数字添加前缀
Posted
技术标签:
【中文标题】重复第 n 个数字直到第 n 个匹配,同时使用 awk sub 在模式中为这些数字添加前缀【英文标题】:Repeat nth number until the nth match while prefixing these number at the pattern using awk sub 【发布时间】:2021-12-15 08:44:26 【问题描述】:下面的文件包含15
次字符串.dog
。
通常,当我想在字符串中添加任何数字以进行计数时,我会使用 awk '/\.dog/sub(".dog",++count"&") 1'
并多次使用此命令的一些变体,就像在这个问题 awk sub ++count every 4 matches unlike every 1 match 中一样。
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
-house
[.cat]
-kitchen
[.dog]
目前我不得不做一些不同的事情,以便将唯一的 nth 数字 附加到 nth 匹配,也就是说,每个 nth 数字 (1, 2, 3, etc.) 重复直到第 nth match。假设我希望它 .dog
成为我的模式,并且 .dog
的 5 nth 匹配 awk.. gsub.. count
命令重复 1 同时附加一个数字。所以我的输出应该是:
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
我一直在寻找解决方案但我没有找到,我相信再次可以找到这个解决方案操纵和适应awk '/\.dog/sub(".dog",++count"&") 1 | <at the every 5 matches> '
但我仍然不确定。
【问题讨论】:
【参考方案1】:$ awk '$0=="[.dog]" if (++cnt % 5 == 1) idx++; sub(/\./,idx".") 1' file
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
【讨论】:
【参考方案2】:你可以试试这个awk
$ awk 'BEGINFS=OFS="[" split($2,a,".")/dog/a[1]=int(dog++/5);$2=a[1]+1"."a[2]1' input_file
通过将dog
的每个匹配项拆分为 20% 或 0.2,这将在一个整数内生成 5 个匹配项,int
抑制浮点小数,因此可能有更好的方法。
输出
$ awk 'BEGINFS=OFS="[" split($2,a,".")/dog/a[1]=int(dog++/5);$2=a[1]+1"."a[2]1' input_file
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[1.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[2.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
-house
[.cat]
-kitchen
[3.dog]
【讨论】:
@Cyrus 评论:awk 'BEGIN count=1 /\.dog/ t=count; sub(/\..*/,"",t); sub(".dog", t "&"); count+=.2 1' file
也有效!【参考方案3】:
用户@Cyrus 的回答:
awk 'BEGIN count=1 /\.dog/ t=count; sub(/\..*/,"",t); sub(".dog", t "&"); count+=.2 1' file
【讨论】:
这做了一些不必要的事情,因此可以简化为awk '/\.dog/ sub(".dog", int(count+1) "&"); count+=.2 1' file
,但它是硬编码.2
,对于除 5 以外的重复次数而言,这并不总是一个很好的简单数字(例如,尝试3)的重复,可能会遇到浮点算术舍入问题,在需要字符串比较时进行正则表达式比较,容易匹配错误的字符串,并且在 sub() 中保留 RE 元字符未转义,因此 YMMV 取决于您的真实情况文件内容。
不要那样做。接受您提出的问题的答案,如果您无法使用更能代表您的真实数据的minimal reproducible example 使解决方案适用于您的真实数据,请提出新的后续问题。 chameleon questions 强烈反对。
我们所能做的就是回答您提出的问题。匹配您想要匹配的文本总是微不足道的,而不匹配您不想匹配的文本则要困难得多。我希望这个答案能够“适应”,因为它比您要求的更匹配,因此它也会“适应”其他事物 - 这是一个错误,而不是一个功能。尝试在示例输入中将.cat
替换为.dogfish
,然后运行这两种解决方案。仅仅因为您没有看到如何修改我对您的真实数据的回答并不意味着它不是对您提出的问题的更好答案和/或处理您的真实数据的更好方法。
这绝对不是我的代码,它试图在文字字符串比较中使用正则表达式元字符,使用这些字符就好像它们是通配符而不是正则表达式字符,并且没有限制你的文本想匹配。如果您有新问题,请将其发布在网站上,并附上它自己的 minimal reproducible example,以便我们为您提供帮助。如果我们不知道您要解析的文本是什么样的,我们将无法帮助您稳健地解析文本。
我不建议将.dog
更改为.dogfish
,我建议将.cat
更改为.dogfish
,这样您就可以看到我的答案继续正确更新.dog
行,而发布的其他答案中的脚本将失败,因为它们还将更新 .dogfish
行。这就是我要告诉你的问题的一种表现 - 匹配你想要的线条总是很容易,但不匹配你不想要的类似线条就更难了。以上是关于重复第 n 个数字直到第 n 个匹配,同时使用 awk sub 在模式中为这些数字添加前缀的主要内容,如果未能解决你的问题,请参考以下文章