基于条件比较当前行和下一行,并根据条件打印其中一行的awk解决方案

9

我有一个输入文件,看起来像这样(第一列是位置号码,第二列是应该随时间增加的计数):

1       0
1       2
1       6
1       7
1       7
1       8
1       7
1       7
1       9
1       9
1       10
1       10
1       9
1       10
1       10
1       10
1       10
1       10
1       10
1       9
1       10
1       10
1       10
1       10
1       10
1       10

我希望您能将其修复为以下样式(用前一个计数替换减少的计数):
1       0
1       2
1       6
1       7
1       7
1       8
1       8
1       8
1       9
1       9
1       10
1       10
1       10
1       10
1       10
1       10
1       10
1       10
1       10
1       10
1       10
1       10
1       10
1       10
1       10
1       10

我一直在尝试使用awk,但是由于无法弄清如何重置行号(NR?),以便它可以读取每一行及其下一行而不是两行,因此遇到了问题。目前我拥有的代码如下,你有什么想法吗?

awk '{a=$1; b=$2; getline; c=$1; d=$2; if (a==c && b<=d) print a"\t"b; else print c"\t"d}' original.txt > fixed.txt

此外,这是我目前得到的输出:
1       0
1       6
1       7
1       7
1       9
1       10
1       9
1       10
1       10
1       9
1       10
1       10
1       10

好的,只是为了澄清一下,您是想要跳过计数减少的行吗?那是很多行,我不知道您是否能给出一个更简短的例子,同样能够清晰表达您的意思? - Levon
抱歉如果我的解释不够清晰,我想在计数减少时打印前一行,以便最终得到相同数量的行,但是文件中的计数保持不变或增加,而不是减少。 - suegene
我明白了..请查看下面提供的答案,我认为你会找到你想要的。 - Levon
2个回答

8
也许你只需要:
awk '$2 < p { $2 = p } { p = $2 } 1' input-file

如果第二列的值为负数,第一行将失败,因此请执行以下操作:
awk 'NR > 1 && $2 < p ...'

如果当前值较小,这将使第二列设置为先前的值,然后将当前值存储在变量p中,最后打印该行。

请注意,这还会略微修改更改行的输出间距。如果您的输入是以制表符分隔的,您可能需要执行以下操作:

awk 'NR > 1 && $2 < p { $2 = p } { p = $2 } 1' OFS=\\t input-file

哇..简洁多了..我想我有你第一个解决方案的冗长版本。 - Levon
太棒了,我刚刚还在试图弄清楚间距问题,谢谢! - suegene

2
这个脚本将会按照您的要求执行:
{
  if ($2 < prev_count)
    $2 = prev_count
  else
    prev_count = $2

  printf("%d   %d\n", $1, $2)
}

这是一个详细的版本,易于阅读 :)

谢谢,我也很欣赏详细版! - suegene
@suegene 很高兴能帮助到你.. 我使用 printf 调整了输出间距,如果你需要更精细的格式和间距控制,这可能会对你有所帮助。 - Levon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接