根据包含数字和不包含数字的行对 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
【讨论】:
我尝试使用awk
和mawk
,但得到“第 1 行:END 或附近的语法错误”和“第 1 行:对数组 a 的非法引用”。
这很奇怪……我尝试了awk
和gawk
,它没有报告任何错误。您是否对脚本进行了任何更改?
很抱歉,看起来 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-统计文件中仅包含数字的行。