我有一个标签分隔的文本文件,我需要检查副本。布局大致是这样的。(文件中的第一个条目是列名。)
示例输入文件:
+--------+-----------+--------+------------+-------------+----------+
| First | Last | BookID | Title | PublisherID | AuthorID |
+--------+-----------+--------+------------+-------------+----------+
| James | Joyce | 37 | Ulysses | 344 | 1022 |
| Ernest | Hemingway | 733 | Old Man... | 887 | 387 |
| James | Joyce | 872 | Dubliners | 405 | 1022 |
| Name1 | Surname1 | 1 | Title1 | 1 | 1 |
| James | Joyce | 37 | Ulysses | 345 | 1022 |
| Name1 | Surname1 | 1 | Title1 | 2 | 1 |
+--------+-----------+--------+------------+-------------+----------+该文件可容纳多达500 K行。我们要做的是检查没有重复的BookID和AuthorID值。例如,在上面的表中,不可能有两行BookID为37和AuthorID 1022。
作者可能会被分组在连续的行中,但不能保证这一点。如果不是,而且很难检查,我可以接受。但否则,如果作者是相同的,我们需要知道是否存在一个重复的BookID。
一个复杂的问题--我们可以在文件中有重复的BookID,但是不允许使用AuthorID +BookID的组合。
是否有一种在bash脚本中检查这一点的好方法,也许是sed和awk的组合,或者是实现这一点的另一种方法?
用于脚本的原始选项卡分隔的文件内容:
First Last BookID Title PublisherID AuthorID
James Joyce 37 Ulysses 344 1022
Ernest Hemingway 733 Old Man... 887 387
James Joyce 872 Dubliners 405 1022
Name1 Surname1 1 Title1 1 1
James Joyce 37 Ulysses 345 1022
Name1 Surname1 1 Title1 2 1发布于 2019-11-11 02:07:23
对于awk来说,这非常容易:
$ awk 'BEGIN { FS = "\t" }
($3,$6) in seen { printf("Line %d is a duplicate of line %d\n", NR, seen[$3,$6]); next }
{ seen[$3,$6] = NR }' input.tsv它将每个bookid、authorid对保存在哈希表中,并警告是否已经存在该对。
发布于 2019-11-11 02:15:28
如果您想查找并计数您可以使用的副本
awk '{c[$3 " " $6]+=1} END { for (k in c) if (c[k] > 1) print k "->" c[k]}',它将组合计数保存在关联数组中,然后在大于1时打印计数。
发布于 2019-11-11 02:33:15
选项卡分隔的文本文件
正在检查没有重复的BookID和AuthorID值。
在@piotr.wittchen中,这些列如下所示:
第一最后一个BookID标题PublisherID AuthorID
这很简单:
columns
cut -f3,6 input_file.txt | sort | uniq -d如果需要整行,我们必须重新排序字段,uniq才能吃掉它们:
awk '{print $1,$2,$4,$5,$3,$6}' input_file.txt | sort -k5 -k6 | uniq -d -f4如果必须将它们按初始顺序排列,则可以对行编号进行编号,得到重复的行号,并将它们与行号重新排序,然后删除行号,如下所示:
nl -w1 input_file.txt |
awk '{print $1,$2,$3,$5,$6,$4,$7}' input_file.txt | sort -k6 -k7 | uniq -d -f5 |
sort -k1 | cut -f2-https://stackoverflow.com/questions/58793125
复制相似问题