在shell中对一个.unl文件进行“去重”。对重复的记录取最后一条记录和原有的数据重新覆盖原有文件,且将重复的记录输入到一个err*.unl文件中...
假设你这个.unl文件叫 file.unl,并且内容不含斜杠 / 。
脚本大致如下:
#!/bin/bash
myfile=file.unl
touch tmp
while read line
do
grep "$line" tmp >/dev/null 2>&1
if [ $? -eq 0 ]; then
num=`awk '{print $NF}' tmp`
num=`expr $num + 1`
sed -i “s/^\($line\t\)[0-9]*$/\1$num/” tmp
else
echo -e "$line\t1" >>tmp
fi
done <$myfile # ---> 1), 2)
awk '$NF>1{print}' tmp >err.unl # ---> 3)
sed -i 's/^\(..*\)\t[0-9]*$/\1/' tmp
mv -f tmp $myfile # ---> 4)
exit 0
思路就是,
1)遍历 unl 文件的每一行,逐行拷贝一份到临时文件tmp中,后面附加一个出现的次数。
2)遍历的同时到tmp文件中去查找是否有已存在的相同记录,如果有,就只是更新tmp文件中记录的次数而不添加一个新记录。
3)最后根据tmp文件中记录的次数是否大于1来生成err.unl文件,记录重复的行及总共出现的次数。
4)将tmp文件中的次数记录去除即得到更新后的 unl 文件。
由于要求要覆盖原unl文件,所以这里存在风险。 建议运行脚本前先备份一下原unl文件。
最后,恕我直言,这个题目的难度不止10分。
你看,while循环,grep / sed / awk,全用上了 ^_^
————————————————————————————————————
发现一个更简练的方法,两条命令即可搞定:
awk '{s[$0]+=1} END{for(a in s) print a, s[a]}' file.unl >err.unl
awk '{print $1}' err.unl >file.unl
当然,前提是unl文件的每行内容不能含有空格或TAB之类的分隔符。
参考了 http://zhidao.baidu.com/question/271261293.html#here 这个问题中shuguangbo童鞋的回答。
脚本大致如下:
#!/bin/bash
myfile=file.unl
touch tmp
while read line
do
grep "$line" tmp >/dev/null 2>&1
if [ $? -eq 0 ]; then
num=`awk '{print $NF}' tmp`
num=`expr $num + 1`
sed -i “s/^\($line\t\)[0-9]*$/\1$num/” tmp
else
echo -e "$line\t1" >>tmp
fi
done <$myfile # ---> 1), 2)
awk '$NF>1{print}' tmp >err.unl # ---> 3)
sed -i 's/^\(..*\)\t[0-9]*$/\1/' tmp
mv -f tmp $myfile # ---> 4)
exit 0
思路就是,
1)遍历 unl 文件的每一行,逐行拷贝一份到临时文件tmp中,后面附加一个出现的次数。
2)遍历的同时到tmp文件中去查找是否有已存在的相同记录,如果有,就只是更新tmp文件中记录的次数而不添加一个新记录。
3)最后根据tmp文件中记录的次数是否大于1来生成err.unl文件,记录重复的行及总共出现的次数。
4)将tmp文件中的次数记录去除即得到更新后的 unl 文件。
由于要求要覆盖原unl文件,所以这里存在风险。 建议运行脚本前先备份一下原unl文件。
最后,恕我直言,这个题目的难度不止10分。
你看,while循环,grep / sed / awk,全用上了 ^_^
————————————————————————————————————
发现一个更简练的方法,两条命令即可搞定:
awk '{s[$0]+=1} END{for(a in s) print a, s[a]}' file.unl >err.unl
awk '{print $1}' err.unl >file.unl
当然,前提是unl文件的每行内容不能含有空格或TAB之类的分隔符。
参考了 http://zhidao.baidu.com/question/271261293.html#here 这个问题中shuguangbo童鞋的回答。
温馨提示:答案为网友推荐,仅供参考
第1个回答 2012-11-25
是否可以这样?
用sort排序一下,然后uniq -c 来去重复并统计。然后用awk 把统计出来超过1的写入到err.unl
sort file.unl|uniq -c > tmp.file
awk '{if($1>1)print $2}>err.unl
awk '{print $2}' tmp.file > file.unl
rm tmp.file
用sort排序一下,然后uniq -c 来去重复并统计。然后用awk 把统计出来超过1的写入到err.unl
sort file.unl|uniq -c > tmp.file
awk '{if($1>1)print $2}>err.unl
awk '{print $2}' tmp.file > file.unl
rm tmp.file
第2个回答 2011-05-21
已知一个文本文件可能存在重复记录,但是ID经过重新编排已经不同了。如何用...不知道是不是Linux的shell,如果是UNIX,就把下面的/bin/bash改为相应的...追问
就是在linux下面的shell,就是对下面的unl数据文件进行操作!
追答已知一个文本文件可能存在重复记录,但是ID经过重新编排已经不同了。如何用...不知道是不是Linux的shell,如果是UNIX,就把下面的/bin/bash改为相应的...