如何在一行中重复数据的末尾放置序列号?

时间:2016-05-19 08:11:23

标签: linux bash shell awk sed

我有一个包含重复信息的文件。线条编号,然后是冒号,然后是信息。我想只在重复信息的末尾加上一个序号。

实施例

输入:

1:Jose da Silva
2:Jose da Silva
3:Fulano de Tal
4:Jose da Silva
5:Sicrano Pereira
6:Ze Ruela
7:Sicrano Pereira
8:Jose da Silva

输出:

1:Jose da Silva #1
2:Jose da Silva #2
3:Fulano de Tal
4:Jose da Silva #3
5:Sicrano Pereira #1
6:Ze Ruela
7:Sicrano Pereira #2
8:Jose da Silva #4

[这个问题与this one不同,因为这里的行总是不同的(每行都有不同的数字)。我的输入/输出示例可能看起来非常相似,但在实际应用中它们不是。]

1 个答案:

答案 0 :(得分:1)

调整my previous answer

awk -F: 'FNR==NR {count[$2]++; next}
         count[$2]>1 {$0=$0 OFS "#"++times[$2]}
         1' file file

即:第一次计算每秒块发生的次数。第二次,继续向出现不止一次的数字附加一个递增的数字。因此,它不是比较整行,而是比较第二个字段,即冒号:中的所有字段。

进一步解释:

  • FNR==NR {actions; next} {more_actions} file1 file2包括在阅读第一个文件时执行某些内容actions,在阅读第二个文件时执行其他more_actions。当你想要比较文件时,这非常方便,就像我们在这里做的那样。但是等等,这里我们只有一个文件,对吗?是的,但这也允许将文件中的行彼此进行比较。有关此内容的更多信息,请参见Idiomatic awk
  • 因此,FNR==NR {count[$2]++; next}会在数组count中存储每个第2个字段出现的次数。这样,Jose da Silva是计数器4次等等。注意我们使用$2作为数组的索引:这是基于我们用{{1}设置的分隔符:的第二个字段}。也就是说,第一个字段是第一个字段-F:,第二个字段是从第一个:到第二个字段的所有内容,依此类推。
  • :这已经是第二次阅读该文件了。在这里,它不断检查当前时间的第二个字段上的计数器是否表示它发生了一次或多次。如果它不止一次,它会向原始字符串count[$2]>1 {$0=$0 OFS "#"++times[$2]}添加一些内容。这是$0
    • OFS "#"++times[$2]是输出字段分隔符。也就是说,打印数据时使用的字段分隔符。由于我们在运行程序之前没有设置它,因此默认为空格。
    • OFS这只是我们想要在柜台前添加的一些文字。
    • "#"这只是一个计数器,用于跟踪到目前为止打印的次数。由于我们有不同的第二个字段,我们需要一个数组++times[$2]来跟踪它们中的每一个。
  • times[]在脚本的最后我们有1。这是打印行的惯用方法:1是真值,1表达式为true时的行为是打印当前行。也就是说,打印awk可以是原始的或具有一些尾随新内容的那个。

输出:

$0