根据包含数字和不包含数字的行对 CSV 中的行进行排序

Posted

技术标签:

【中文标题】根据包含数字和不包含数字的行对 CSV 中的行进行排序【英文标题】:Sorting the lines in a CSV according to those containing numbers and those without 【发布时间】:2012-02-17 13:25:28 【问题描述】:

我有一个 4 列的 CSV 文件。我想对这些行进行排序,以便将第三列中某处包含任何数字的行推到文档的末尾,将第三列中没有数字的行放在开头。如何以这种方式对文件进行排序?

更新:

为了澄清,我需要在第三列的字母中移动包含任何数字(即匹配[0-9])的行(该行的第三列可能包含其他符号)。空格并不重要。例如

dog, eats chicken, has 4 legs, does not like cats
cat, eats mice, has a tail, does not like water
mouse, eats bugs, has 4 legs, does not like cats
elephant, eats peanuts, has a trunk, does not like mice

将被排序到:

cat, eats mice, has a tail, does not like water
elephant, eats peanuts, has a trunk, does not like mice
dog, eats chicken, has 4 legs, does not like cats
mouse, eats bugs, has 4 legs, does not like cats

【问题讨论】:

【参考方案1】:

这将保持处理行的顺序以及不使用管道和外部命令。

awk -F, '
$3~/[0-9]+/a[++i]=$0;x=i;next1
ENDfor(i=1;i<=x;i++) print a[i]' file

输入文件:

[jaypal:~/Temp] cat file
dog, eats chicken, has 4 legs, does not like cats
cat, eats mice, has a tail, does not like water
mouse, eats bugs, has 4 legs, does not like cats
elephant, eats peanuts, has a trunk, does not like mice

测试:

[jaypal:~/Temp] awk -F, '
$3~/[0-9]+/a[++i]=$0;x=i;next1
ENDfor(i=1;i<=x;i++) print a[i]' file
cat, eats mice, has a tail, does not like water
elephant, eats peanuts, has a trunk, does not like mice
dog, eats chicken, has 4 legs, does not like cats
mouse, eats bugs, has 4 legs, does not like cats

【讨论】:

我尝试使用awkmawk,但得到“第 1 行:END 或附近的语法错误”和“第 1 行:对数组 a 的非法引用”。 这很奇怪……我尝试了awkgawk,它没有报告任何错误。您是否对脚本进行了任何更改? 很抱歉,看起来 length(a) 引用导致您的 awk 版本出现问题。您能否尝试更新的解决方案。我进行了更改以删除该功能。【参考方案2】:

这是 awk 中的一个简短的 1-liner,不需要调用其他实用程序,例如 sort

awk -F',' '$3 ~ /[[:digit:]]/a[$0];next1; ENDfor(i in a)print i' ./infile

说明

如果第三个字段包含数字,则将当前行作为键存储在数组“a”中并处理下一行 如果所有行不符合上述规则,则按原样输出 处理完所有行后,输出我们存储在数组“a”中的行

输出

$ awk -F',' '$3 ~ /[[:digit:]]/a[$0];next1; ENDfor(i in a)print i' ./infile
cat, eats mice, has a tail, does not like water
elephant, eats peanuts, has a trunk, does not like mice
mouse, eats bugs, has 4 legs, does not like cats
dog, eats chicken, has 4 legs, does not like cats

【讨论】:

这段代码似乎只对第三行仅包含数字的行进行排序。我需要对至少包含一个数字的行进行排序,但它们可能在同一单元格中有其他字符。 你试过运行它吗?它适用于您的新示例输入。正则表达式$3 ~ /[[:digit:]]/ 匹配任何包含至少一位数字的第三个字段,而不管它主要包含的其他内容。【参考方案3】:

这样的事情应该可以工作:

awk 'BEGIN FS=","; OFS=","; print match($3,/[0-9]/), $0' <file> | sort | cut -d, -f2-

策略是

使用awk在每行的开头插入找到数字的索引(如果没有找到数字,则为0) 使用sort对所有行进行排序 最后,使用cut 删除awk 前面的数字。

【讨论】:

我需要在第三列中搜索至少包含一个数字的单元格,而不仅仅是只包含数字的单元格。 @Village 我明白了,我已经修改了我的答案以考虑到这一点。【参考方案4】:

这可能对你有用:

sed 'h;s/,/\n/2;s/.*\n/0/;s/,.*//;s/[^0-9]//g;G;s/\n/\t/' file | 
sort -k1,1n -k2 | 
cut -f2

解释:

使用第 3 列中的数字生成数字键(如果没有,则将键设置为 0) 按上述键排序,再按原文件排序 去掉数字键

【讨论】:

|放在行尾是什么意思? @Village 这是管道命令。这是一个单行解决方案,我只是将其拆分以使其更易于阅读,

以上是关于根据包含数字和不包含数字的行对 CSV 中的行进行排序的主要内容,如果未能解决你的问题,请参考以下文章

如何编写oracle SQL查询以特定顺序获取匹配和不匹配的行对(基于键列)

Linux脚本练习之script046-统计文件中仅包含数字的行。

如何在 MYSQL 中选择包含所有字母和数字的行?

取所有包含数字的行的总和并跳过带有字母的行并将总和写回另一个文件

从数据框的行中删除仅包含数字的字符串

如何搜索包含非字母数字或空格字符的行?