我的参考资料是一个文本文件,其中包含一长串条目,每个条目都有两个(或更多)字段。
第一列是参考文献的 URL;第二列是标题,根据条目的制作方式可能会有所不同。第三列也是一样,可能会出现,也可能不存在。
我想识别但不删除第一个字段(引用 URL)相同的条目。我知道,sort -k1,1 -u
但这会自动(非交互地)删除除第一个匹配项之外的所有匹配项。有没有办法让我知道,以便我可以选择保留哪些匹配项?
下面的三行代码中,有相同的第一个字段(http://unix.stackexchange.com/questions/49569/
),我想保留第 2 行,因为它有附加标签(sort、CLI),并删除第 1 行和第 3 行:
http://unix.stackexchange.com/questions/49569/ unique-lines-based-on-the-first-field
http://unix.stackexchange.com/questions/49569/ Unique lines based on the first field sort, CLI
http://unix.stackexchange.com/questions/49569/ Unique lines based on the first field
有没有程序可以帮助识别此类“重复”?然后,我可以通过亲自删除第 1 行和第 3 行来手动清理?
答案1
这是一个经典问题,可以用命令解决uniq
。uniq
可以检测重复连续的行并删除重复项 ( -u
, --unique
) 或仅保留重复项 ( -d
, --repeated
)。
由于重复行的顺序对你来说并不重要,你应该先对其进行排序。然后使用它uniq
仅打印唯一的行:
sort yourfile.txt | uniq -u
还有一个-c
( --count
) 选项,用于打印该选项的重复项数-d
。有关详细信息,请参阅手册页uniq
。
如果您确实不关心第一个字段之后的部分,您可以使用以下命令来查找重复的键并打印其每个行号(附加另一个| sort -n
以使输出按行排序):
cut -d ' ' -f1 .bash_history | nl | sort -k2 | uniq -s8 -D
由于您想要查看重复的行(使用第一个字段作为键),因此您不能直接使用uniq
。使自动化变得困难的问题是标题部分各不相同,但程序无法自动确定哪个标题应被视为最后一个标题。
这是一个 AWK 脚本(将其保存到script.awk
),它将您的文本文件作为输入并打印所有重复的行,以便您可以决定删除哪些行。(awk -f script.awk yourfile.txt
)
#!/usr/bin/awk -f
{
# Store the line ($0) grouped per URL ($1) with line number (NR) as key
lines[$1][NR] = $0;
}
END {
for (url in lines) {
# find lines that have the URL occur multiple times
if (length(lines[url]) > 1) {
for (lineno in lines[url]) {
# Print duplicate line for decision purposes
print lines[url][lineno];
# Alternative: print line number and line
#print lineno, lines[url][lineno];
}
}
}
}
答案2
如果我理解你的问题,我认为你需要类似以下内容的内容:
for dup in $(sort -k1,1 -u file.txt | cut -d' ' -f1); do grep -n -- "$dup" file.txt; done
或者:
for dup in $(cut -d " " -f1 file.txt | uniq -d); do grep -n -- "$dup" file.txt; done
file.txt
包含您感兴趣的数据的文件在哪里?
在输出中,您将看到行数以及第一个字段出现两次或更多次的行数。
答案3
如果我没看错的话,你所需要的只是
awk '{print $1}' file | sort | uniq -c |
while read num dupe; do [[ $num > 1 ]] && grep -n -- "$dupe" file; done
这将打印出包含重复项的行号和行本身。例如,使用此文件:
foo bar baz
http://unix.stackexchange.com/questions/49569/ unique-lines-based-on-the-first-field
bar foo baz
http://unix.stackexchange.com/questions/49569/ Unique lines based on the first field sort, CLI
baz foo bar
http://unix.stackexchange.com/questions/49569/ Unique lines based on the first field
它将产生以下输出:
2:http://unix.stackexchange.com/questions/49569/ unique-lines-based-on-the-first-field
4:http://unix.stackexchange.com/questions/49569/ Unique lines based on the first field sort, CLI
6:http://unix.stackexchange.com/questions/49569/ Unique lines based on the first field
要仅打印行号,你可以这样做
awk '{print $1}' file | sort | uniq -c |
while read num dupe; do [[ $num > 1 ]] && grep -n -- "$dupe" file; done | cut -d: -f 1
并且只打印该行:
awk '{print $1}' file | sort | uniq -c |
while read num dupe; do [[ $num > 1 ]] && grep -n -- "$dupe" file; done | cut -d: -f 2-
解释:
该awk
脚本仅打印文件的第一个空格分隔字段。用于$N
打印第 N 个字段。sort
对其进行排序并uniq -c
计算每行的出现次数。
然后将其传递给while
循环,该循环将出现的次数保存为,$num
并将行保存为,$dupe
如果$num
大于一(因此至少重复一次),它将在文件中搜索该行,并使用-n
打印行号。--
表示grep
后面的内容不是命令行选项,在$dupe
以 开头时很有用-
。
答案4
请参阅以下排序file.txt
:
addons.mozilla.org/en-US/firefox/addon/click-to-play-per-element/ ::: C2P per-element
addons.mozilla.org/en-us/firefox/addon/prospector-oneLiner/ ::: OneLiner
askubuntu.com/q/21033 ::: What is the difference between gksudo and gksu?
askubuntu.com/q/21148 ::: openoffice calc sheet tabs (also askubuntu.com/q/138623)
askubuntu.com/q/50540 ::: What is Ubuntu's Definition of a "Registered Application"?
askubuntu.com/q/53762 ::: How to use lm-sensors?
askubuntu.com/q/53762 ::: how-to-use-to-use-lm-sensors
stackoverflow.com/q/4594319 ::: bash - shell replace cr\lf by comma
stackoverflow.com/q/4594319 ::: shell replace cr\lf by comma
wiki.ubuntu.com/ClipboardPersistence ::: ClipboardPersistence
wiki.ubuntu.com/ClipboardPersistence ::: ClipboardPersistence - Ubuntu Wiki
www.youtube.com/watch?v=1olY5Qzmbk8 ::: Create new mime types in Ubuntu
www.youtube.com/watch?v=2hu9JrdSXB8 ::: Change mouse cursor
www.youtube.com/watch?v=Yxfa2fXJ1Wc ::: Mouse cursor size
因为列表很短,所以我可以看到(排序后)有三组重复项。
然后,例如,我可以选择保留:
askubuntu.com/q/53762 ::: How to use lm-sensors?
而不是
askubuntu.com/q/53762 ::: how-to-use-to-use-lm-sensors
但对于较长的列表,这将很困难。根据两个答案,一个建议uniq
,另一个建议cut
,我发现此命令给出了我想要的输出:
$ cut -d " " -f1 file.txt | uniq -d
askubuntu.com/q/53762
stackoverflow.com/q/4594319
wiki.ubuntu.com/ClipboardPersistence
$