【问题标题】:Shell script to merge two list and remove duplicates用于合并两个列表并删除重复项的 Shell 脚本
【发布时间】:2010-06-22 17:10:02
【问题描述】:

我有以下代码:

get_list_a() { $MYSQL -B -u $USER --passwword="$PW" $DB1 $test.txt

现在我需要先合并 a 和 b 并删除所有 dups(键是名称,第一列),然后将它们写入 test.txt。假设列表 a 和列表 b 本身是不同的。如果 a 中的 x 和 b 中的 y 存在使得 x.name=y.name,那么我只想保留 x。 我该怎么做?注意:在 SQL 中合并不是一个选项,因为它们位于不同的数据库中,具有不同的排序规则。

一个例子:
get_list_a 打印

啊啊啊啊啊啊 ccc ddd

get_list_b 打印

啊啊啊啊啊 呸呸呸

我希望将以下内容写入文件:

啊啊啊啊啊啊 ccc ddd 呸呸呸

【问题讨论】:

  • 样本输出中的“nnn”应该是“bbb”吗?
  • 这个问题更适合 Stack Overflow;很快就会迁移到那里。

标签: mysql shell list


【解决方案1】:

这样的 SQL 查询会起作用吗? (未经测试)

SELECT COALESCE(x.name,y.name),COALESCE(x.value,y.value)
FROM mytable_a AS x
FULL JOIN mytable_b AS y
ON x.name = y.name;

编辑:好的,如果它们位于单独的 DB 中,并且字段以空格分隔,如您在评论中指出的那样,我可能会在 perl 或 awk 中使用关联数组,让 x (a) 中的值覆盖来自 y (b) 的值。像这样的东西(尚未测试):

get_list_a > x.txt
get_list_b > y.txt
cat y.txt x.txt | awk '{ data[$1] = $2; } END { for (i in data) { print i, data[i]; }}'

【讨论】:

  • 不,首先,它们来自两个具有不同排序规则的数据库,我无法加入它们。其次,合并不是简单地返回第一个非空参数吗?名称或值永远不会为空。
  • 在您对问题的陈述中,没有迹象表明它们来自不同的数据库(在这两种情况下都只是“$DB”)。如果名称/值仅出现在两个表之一中,我认为您将在完全连接中获得 NULL。
  • 我已经编辑了我的问题以反映要求。只是好奇 SQL 将如何解决删除优先于 x 超过 y 的重复数据?
  • 如果我写得正确,优先级由 COALESCE 表达式中的参数顺序处理。也就是说,如果 x.value 和 y.value 都不是 NULL(因为两个表都有该名称的值),则 x.value 先出现并优先。
  • 脚本中的 END 是用来分隔语句的吗?
【解决方案2】:

只是为了“好玩”,这里是一个使用 sed 且没有临时文件(只是变量)的解决方案:

x=$(get_list_a) 
y=$(get_list_b)

while read name value
do 
    y=$(echo "$y" | sed "/^$name/ d")
done << EOF
$x
EOF

echo "$x"
echo "$y"

【讨论】:

    【解决方案3】:

    你能把你的问题说得更清楚一点吗?您能否提供一些您期望的简短示例输入和示例输出?有点不清楚你在问什么。

    编辑:根据您的需要,这应该可以解决问题:

    get_a  > inputfile
    get_b >> inputfile
    perl -lne '$data{$F[0]} = $F[1] unless exists $data{$F[0]} }{ for $key (keys %data) { print "$key $data{$key}\n"}' inputfile > outputfile
    

    }{ 是因为调用perl -n 会导致程序(由-e 给出)被包装在隐式while (&lt;STDIN&gt;) { ... } 块中。 } 关闭 while{ 打开一个新代码块,该代码块一直运行到隐含的 }

    使用-l 调用 perl 会导致其输入自动拆分为 @F,类似于 awk 的 $1$2 等。然后将键/值对添加到 %data除非钥匙已经在那里。

    【讨论】:

    • 你可以把这个作为评论提出来
    • 这个 }{ 看起来很奇怪,括号似乎不匹配,你能解释一下吗?
    • 输入文件有a.txt和b.txt两个,你的脚本只显示一个?
    • 我见过}{ 是这样使用的。伊克。试试stuff_for_each_loop; END { final_statements; }
    【解决方案4】:

    您是仅删除重复键或值上的重复项吗?

    命令 sort -u 删除重复项(字母 u 表示“唯一”)。它具有以字符开始和结束列表示的排序键值的选项。它可能很简单(假设固定值长度或固定列格式):

    get_list_a >$test.txt
    get_list_b >>$test.txt
    sort -u test.txt -k<startcol>,<endcol> test.txt > output.txt
    

    当然,我宁愿在 SQL 中进行合并。

    【讨论】:

    • 我只删除重复键上的重复项。对于重复键,列表 a 优先于列表 b。
    • 另一件事是每列都用空格分隔,但列宽不固定。如何使用 sort -k, 按第一列(键)进行排序
    猜你喜欢
    • 2017-06-05
    • 2015-09-20
    • 2015-11-29
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    相关资源
    最近更新 更多