是否可以使用 bash 在一列中找到具有重复值但在其他列中没有重复值的数据?
Is it possible to find data that have duplicate values in one column but not others using bash?
我有一个包含多列和多行的文件。我想获取数据并找到第 4 列中重复值的行,然后将这些行打印到新文件中。
我的数据文件如下所示:
RR2.out -1752.142111 -1099486.696073 0.000000
SS2.out -1752.142111 -1099486.696073 0.000000
RR1.out -1752.141887 -1099486.555511 0.140562
SS1.out -1752.141887 -1099486.555511 0.140562
RR4.out -1752.140564 -1099485.725315 0.970758
SS4.out -1752.140564 -1099485.725315 0.970758
RR3.out -1752.140319 -1099485.571575 1.124498
SS3.out -1752.140319 -1099485.571575 1.124498
SS5.out -1752.138532 -1099484.450215 2.245858
RR6.out -1752.138493 -1099484.425742 2.270331
SS6.out -1752.138493 -1099484.425742 2.270331
file Gibbs kcal rel
file Gibbs kcal rel
如果我只使用 uniq -d 我只会得到
file Gibbs kcal rel
file Gibbs kcal rel
因为它们是唯一完全匹配的两条线。我想知道的是,是否有一种方法可以找到第 4 列中具有重复值的所有行,而不总是完全匹配。
然后我使用 awk 和 read 读取第 1 列中的文件名,因此理想情况下我不必将数据传输到另一个文件然后再返回,因为我发现这会导致相关错误读取文件名。
在这个例子中,我应该得到以下文件作为输出:
RR2.out -1752.142111 -1099486.696073 0.000000
SS2.out -1752.142111 -1099486.696073 0.000000
RR1.out -1752.141887 -1099486.555511 0.140562
SS1.out -1752.141887 -1099486.555511 0.140562
RR4.out -1752.140564 -1099485.725315 0.970758
SS4.out -1752.140564 -1099485.725315 0.970758
RR3.out -1752.140319 -1099485.571575 1.124498
SS3.out -1752.140319 -1099485.571575 1.124498
RR6.out -1752.138493 -1099484.425742 2.270331
SS6.out -1752.138493 -1099484.425742 2.270331
file Gibbs kcal rel
file Gibbs kcal rel
这里有一些代码可以完成您正在寻找的内容:
awk ' BEGIN { OLD4 = "No match" }
== OLD4 { print LAST ; print }
{ OLD4 = ; LAST = [=10=] } '
所以这就是您可能 运行 它的方式:
awk ' BEGIN { OLD4 = "No match" }
== OLD4 { print LAST ; print }
{ OLD4 = ; LAST = [=11=] } ' inputfile
输入文件看起来像这样:
RR2.out -1752.142111 -1099486.696073 0.000000
SS2.out -1752.142111 -1099486.696073 0.000000
RR1.out -1752.141887 -1099486.555511 0.140562
SS1.out -1752.141887 -1099486.555511 0.140562
RR4.out -1752.140564 -1099485.725315 0.970758
SS4.out -1752.140564 -1099485.725315 0.970758
RR3.out -1752.140319 -1099485.571575 1.124498
SS3.out -1752.140319 -1099485.571575 1.124498
SS5.out -1752.138532 -1099484.450215 2.245858
RR6.out -1752.138493 -1099484.425742 2.270331
SS6.out -1752.138493 -1099484.425742 2.270331
file Gibbs kcal rel
file Gibbs kcal rel
此程序存在问题,它假设第 4 列已排序。如果确实如此,您可以使用未修改的代码。否则,在将输入传递给 awk 之前按第 4 列对输入进行排序可能是值得的。
要更正排序问题,您可能需要在将文件输入 awk 时对其进行排序。这将改变输出的顺序,因此可能需要更多编码。
这是带有某种输入的 awk 脚本:
awk ' BEGIN { OLD4 = "No match" }
== OLD4 { print LAST ; print }
{ OLD4 = ; LAST = [=13=] } ' <( sort -k4,4 inputfile )
或者:
sort -k4,4 inputfile | awk ' BEGIN { OLD4 = "No match" }
== OLD4 { print LAST ; print }
{ OLD4 = ; LAST = [=14=] } '
uniq
有 -f
/--skip-fields
选项来忽略每行的前 n 个字段。
uniq -D -f3
我有一个包含多列和多行的文件。我想获取数据并找到第 4 列中重复值的行,然后将这些行打印到新文件中。
我的数据文件如下所示:
RR2.out -1752.142111 -1099486.696073 0.000000
SS2.out -1752.142111 -1099486.696073 0.000000
RR1.out -1752.141887 -1099486.555511 0.140562
SS1.out -1752.141887 -1099486.555511 0.140562
RR4.out -1752.140564 -1099485.725315 0.970758
SS4.out -1752.140564 -1099485.725315 0.970758
RR3.out -1752.140319 -1099485.571575 1.124498
SS3.out -1752.140319 -1099485.571575 1.124498
SS5.out -1752.138532 -1099484.450215 2.245858
RR6.out -1752.138493 -1099484.425742 2.270331
SS6.out -1752.138493 -1099484.425742 2.270331
file Gibbs kcal rel
file Gibbs kcal rel
如果我只使用 uniq -d 我只会得到
file Gibbs kcal rel
file Gibbs kcal rel
因为它们是唯一完全匹配的两条线。我想知道的是,是否有一种方法可以找到第 4 列中具有重复值的所有行,而不总是完全匹配。
然后我使用 awk 和 read 读取第 1 列中的文件名,因此理想情况下我不必将数据传输到另一个文件然后再返回,因为我发现这会导致相关错误读取文件名。
在这个例子中,我应该得到以下文件作为输出:
RR2.out -1752.142111 -1099486.696073 0.000000
SS2.out -1752.142111 -1099486.696073 0.000000
RR1.out -1752.141887 -1099486.555511 0.140562
SS1.out -1752.141887 -1099486.555511 0.140562
RR4.out -1752.140564 -1099485.725315 0.970758
SS4.out -1752.140564 -1099485.725315 0.970758
RR3.out -1752.140319 -1099485.571575 1.124498
SS3.out -1752.140319 -1099485.571575 1.124498
RR6.out -1752.138493 -1099484.425742 2.270331
SS6.out -1752.138493 -1099484.425742 2.270331
file Gibbs kcal rel
file Gibbs kcal rel
这里有一些代码可以完成您正在寻找的内容:
awk ' BEGIN { OLD4 = "No match" }
== OLD4 { print LAST ; print }
{ OLD4 = ; LAST = [=10=] } '
所以这就是您可能 运行 它的方式:
awk ' BEGIN { OLD4 = "No match" }
== OLD4 { print LAST ; print }
{ OLD4 = ; LAST = [=11=] } ' inputfile
输入文件看起来像这样:
RR2.out -1752.142111 -1099486.696073 0.000000
SS2.out -1752.142111 -1099486.696073 0.000000
RR1.out -1752.141887 -1099486.555511 0.140562
SS1.out -1752.141887 -1099486.555511 0.140562
RR4.out -1752.140564 -1099485.725315 0.970758
SS4.out -1752.140564 -1099485.725315 0.970758
RR3.out -1752.140319 -1099485.571575 1.124498
SS3.out -1752.140319 -1099485.571575 1.124498
SS5.out -1752.138532 -1099484.450215 2.245858
RR6.out -1752.138493 -1099484.425742 2.270331
SS6.out -1752.138493 -1099484.425742 2.270331
file Gibbs kcal rel
file Gibbs kcal rel
此程序存在问题,它假设第 4 列已排序。如果确实如此,您可以使用未修改的代码。否则,在将输入传递给 awk 之前按第 4 列对输入进行排序可能是值得的。
要更正排序问题,您可能需要在将文件输入 awk 时对其进行排序。这将改变输出的顺序,因此可能需要更多编码。
这是带有某种输入的 awk 脚本:
awk ' BEGIN { OLD4 = "No match" }
== OLD4 { print LAST ; print }
{ OLD4 = ; LAST = [=13=] } ' <( sort -k4,4 inputfile )
或者:
sort -k4,4 inputfile | awk ' BEGIN { OLD4 = "No match" }
== OLD4 { print LAST ; print }
{ OLD4 = ; LAST = [=14=] } '
uniq
有 -f
/--skip-fields
选项来忽略每行的前 n 个字段。
uniq -D -f3