我有一个看起来像这样的平面文件
cat file
ID1, VALUE1_1
ID1, VALUE1_2
ID1, VALUE1_3
ID2, VALUE2_1
ID2, VALUE2_1
ID3, VALUE3_1
ID3...
从数据样本中可以看出,对于每个ID,该ID有几个值,它们可以是任何值 - 相同或不相同。对我而言,我并不关心它正在捡到什么价值。任何价值对我都有用。
所以我只想要每个ID中的一个值。我真的不在乎哪一个,但如果我必须选择,我会说最长的一行。
ID1, VALUE1_2
ID2, VALUE2_1
ID3, VALUE3_1
它可能是用Python完成的,但在Shell本身有一个简单的方法,我可以使用sed或awk,但请不要写一整段awk代码,请...
它可能看起来像:
# Pseudo code
# sort -k 1 file | uniq (max(length) by id)
非常感谢!!
答案 0 :(得分:3)
编辑:
所以我完全根据你的说法重写了我的答案。它有几行,但希望这是你正在寻找的:
为了在Mysql中找到类似于组的“每个ID”中的最大行,我会执行以下操作。
给出以下文本文件:
[root@dev7 ~]# cat stackoverflow2.log
ID1, fdsgfdsggfdsgsdfg
ID1, fdsgsdfg
ID1, fdsgfdgdsfgdsgsdfgdgffdsgfsdg
ID1, fdsgsdfg
ID2, fdgsfdsgfdshshdsfhdfghdsfhdfhdshsdfhsfdh
ID2, fsfgsdgf
ID3, fdgfdgdgfdggfdg
[root@dev7 ~]#
我会做以下事情:
_DATAFILE=stackoverflow2.log
_KEYS=$(awk '{ $1=$1; print $1}' ${_DATAFILE} | uniq | sed "s,\,,,g" | xargs )
_LARGEST_PER_KEY=""
echo $_KEYS
for i in ${_KEYS}; do
_LARGEST_PER_KEY="${_LARGEST_PER_KEY}\n$(grep "$i" ${_DATAFILE} | uniq | awk '{ print length ":", $0 }' | sort -n -u | tail -1 | cut -d ":" -f2 | awk '{ $1=$1; print}')"
done;
echo -e ${_LARGEST_PER_KEY}
解释发生了什么。
[root @ dev7~]#_KEYS = $(awk'{$ 1 = $ 1; print $ 1}'$ {_ DATAFILE} | uniq | sed“s,\ ,,, g”| xargs)
[root @ dev7~] #echo $ _KEYS
ID1 ID2 ID3
_LARGEST_PER_KEY - 这个变量将在我们完成后用于您的结果。我们在for循环之前定义它。
for循环为任务中的键执行grep(例如ID1),然后执行我的代码行以确定哪一个包含最长的数据值,并执行numeric / uniq排序以查看哪一个是最大的。我们使用tail获取该值并将其附加到_LARGEST_PER_KEY字符串。 (注意:我们添加\ n字符作为分隔符)
ONCE完成for循环后,我们使用echo -e回显结果,以确保在屏幕上正确评估换行符:
[root @ dev7~] #echo -e $ {_ LARGEST_PER_KEY}
ID1,fdsgfdgdsfgdsgsdfgdgffdsgfsdg
ID2,fdgsfdsgfdshshdsfhdfghdsfhdfhdshsdfhsfdh
ID3,fdgfdgdgfdggfdg
注意:由于我们在开头对所有内容进行了排序,因此没有理由再次排序。
澄清说明:
awk'{$ 1 = $ 1; print}' - 这将删除尾随空格(行尾/行尾)
uniq - 删除重复项
awk'{print length“:”,$ 0}' - 获取每一行的行长,用“行的长度”打印出来:“行测试”
sort -n -u - 数字排序(最大数字是最后一项)。还确保整个文件在数据文件中唯一排序 到达未分类。谢谢你的提示 Glenn
尾巴-1 - 抓住最大的
以来的最后一行cut -d“:” - f2 - 如果你只想要确切的行,摆脱行的长度只需返回行
awk'{$ 1 = $ 1; print}' - 这将删除尾随空格(行尾/行尾)
再次,我确定这是一种更有效率的方法,但这是我能够提出的。希望这有帮助!
答案 1 :(得分:2)
这将找到每个ID的第一行:
awk -F, '!seen[$1]++' file
说明:
seen[$1]
的值为零(对于数字上下文)。 seen[$1]++
后递增关联数组元素,以便表达式在第一次看到ID时计算为零,并在任何其他时间计算为某个正整数。!
运算符否定后增量表达式。现在我们只有在第一次看到ID时才有真正的表达式:!seen[$1]++
condition1 {body1} condition2 {body2} ...
。
body
仅在其对应的condition
评估为true时执行。 {print}
总而言之,只要表达式的计算结果为true,这个awk程序就会打印当前记录,这只是第一次看到ID。
如果您真的想要每个ID的最长行:
awk '
length($2) > max[$1] {max[$1] = length($2); line[$1] = $0}
END {for (id in line) {print line[id]}}
' file
这可能会改变id的顺序(关联数组是无序集合)。如果这是一个问题,您可以随时将其输入sort
。
答案 2 :(得分:1)
这个awk脚本应该做你想要的,假设文件已经排序:
awk 'prev!=$1{print}{prev=$1}' datafile
测试:
$ cat datafile
ID1, VALUE1_1
ID1, VALUE1_2
ID1, VALUE1_3
ID2, VALUE2_1
ID2, VALUE2_1
ID3, VALUE3_1
$ awk 'prev!=$1{print}{prev=$1}' datafile
ID1, VALUE1_1
ID2, VALUE2_1
ID3, VALUE3_1
说明:
prev!=$1{print}
部分表示:如果变量prev
的值与记录中的第一个字段不同,则打印该行{prev=$1}
部分表示:将变量prev设置为记录中第一个字段的值。 默认情况下,字段由空格分隔(除非使用-F
选项),并且记录由换行符分隔。