jon*_*rry 78 text-processing sort table
我从一个程序中获取输出,该程序首先生成一行,即一堆列标题,然后是一堆数据行。我想剪切此输出的各个列并查看它根据各个列排序。在没有标题的情况下,通过-k选择与列sort一起cut或awk查看列的子集,可以轻松完成剪切和排序。但是,这种排序方法将列标题与输出的其余行混合在一起。有没有一种简单的方法可以将标题保持在顶部?
Mik*_*kel 77
窃取 Andy 的想法并使其成为一个函数,以便更易于使用:
# print the header (the first line of input)
# and then run the specified command on the body (the rest of the input)
# use it in a pipeline, e.g. ps | body grep somepattern
body() {
IFS= read -r header
printf '%s\n' "$header"
"$@"
}
Run Code Online (Sandbox Code Playgroud)
现在我可以这样做:
$ ps -o pid,comm | body sort -k2
PID COMMAND
24759 bash
31276 bash
31032 less
31177 less
31020 man
31167 man
...
$ ps -o pid,comm | body grep less
PID COMMAND
31032 less
31177 less
Run Code Online (Sandbox Code Playgroud)
And*_*ndy 47
您可以使用 bash 将标题保持在顶部:
command | (read -r; printf "%s\n" "$REPLY"; sort)
Run Code Online (Sandbox Code Playgroud)
或者用 perl 来做:
command | perl -e 'print scalar (<>); print sort { ... } <>'
Run Code Online (Sandbox Code Playgroud)
小智 38
我发现了一个很好的 awk 版本,它在脚本中运行良好:
awk 'NR == 1; NR > 1 {print $0 | "sort -n"}'
Run Code Online (Sandbox Code Playgroud)
moreutilspee中的命令是为此类任务而设计的。
例子:
要保留一个标题行,并对第二个(数字)列进行排序stdin:
<your command> | pee 'head -n 1' 'tail -n +2 | sort -k 2,2 -n'
Run Code Online (Sandbox Code Playgroud)
解释:
pee:将 stdin 通过管道传输到一个或多个命令并连接结果。
head -n 1:打印标准输入的第一行。
tail -n +2:从标准输入打印第二行及以下行。
sort -k 2,2 -n:按第二列数字排序。
测试:
printf "header\na 1\nc 3\nb 2\n" | pee 'head -n 1' 'tail -n +2 | sort -k 2,2 -n'
Run Code Online (Sandbox Code Playgroud)
给出
header
a 1
b 2
c 3
Run Code Online (Sandbox Code Playgroud)
Hackish 但有效:在排序之前添加0到所有标题行和1所有其他行。排序后去掉前缀。
… |
awk '{print (NR <= 2 ? "0 " : "1 ") $0}' |
sort -k 1 -k… |
cut -b 3-
Run Code Online (Sandbox Code Playgroud)