问题
我有一个类似这样的CSV文件
代码语言:javascript复制AS2345,ASDF1232, Mr. Plain Example, 110 Binary ave.,Atlantis,RI,12345,(999)123-5555,1.56
AS2345,ASDF1232, Mrs. Plain Example, 1121110 Ternary st. 110 Binary ave..,Atlantis,RI,12345,(999)123-5555,1.56
AS2345,ASDF1232, Mr. Plain Example, 110 Binary ave.,Liberty City,RI,12345,(999)123-5555,1.56
AS2345,ASDF1232, Mr. Plain Example, 110 Ternary ave.,Some City,RI,12345,(999)123-5555,1.56
我需要按包括空格在内的行长度排序。下面的命令不包括空格,有没有办法修改它,使它为我工作?
代码语言:javascript复制cat textfile | awk '{ print length, $0 }' | sort -n | awk '{$1=""; print $0}'
回答
可以使用如下命令:
代码语言:javascript复制awk '{ print length, $0 }' textfile | sort -n | cut -d" " -f2-
{ print length, $0 }
: 是一个简单的 awk
脚本,它对文件的每一行执行以下操作:
length
: 返回当前行的字符数(包括空格和换行符)。$0
: 表示整个当前行的内容。
sort
命令,用于对输入进行排序。
-n
: 指定按照数值顺序进行排序,这里是指按行长度排序。
cut
命令,用于从每行中选择或删除字段。
-d" "
: 设置字段分隔符为空格。-f2-
: 指定从第二个字段开始输出所有字段。
结合前面两步的结果,cut -d" " -f2-
将移除每行的第一个字段(即行长度),保留后面的字段(即原始的行内容)。
为什么提问者的尝试解决方案会失败?
有趣的是,我们可以注意到两者之间的差异:
代码语言:javascript复制echo "hello awk world" | awk '{print $0}'
echo "hello awk world" | awk '{$1="hello"; print $0}'
它们各自输出:
代码语言:javascript复制hello awk world
hello awk world
(gawk 的)手册中只是顺便提到,当你更改一个字段时,awk 将会根据分隔符等重新构建整个 $0
。我猜这不是疯狂的行为。其中写道:
代码语言:javascript复制“最后,有时候为了方便起见,需要强制让 awk 根据当前字段的值和输出字段分隔符(OFS) 重新构建整个记录。要做到这一点,可以使用看似无害的赋值操作:”
$1 = $1 # force record to be reconstituted
print $0 # or whatever else with $0
“这迫使 awk 重建记录。”
参考
- stackoverflow question 5917576
- man awk
- man cut