it-swarm-ru.tech

сортировать, но держать строку заголовка вверху

Я получаю вывод из программы, которая сначала создает одну строку, которая представляет собой группу заголовков столбцов, а затем группу строк данных. Я хочу вырезать различные столбцы этого вывода и просматривать их отсортированные по различным столбцам. Без заголовков вырезание и сортировка легко осуществляются с помощью -k опция sort вместе с cut или awk для просмотра подмножества столбцов. Однако этот метод сортировки смешивает заголовки столбцов с остальными строками вывода. Есть ли простой способ держать заголовки наверху?

63
jonderry

Похищение идеи Энди и превращение ее в функцию, облегчающую ее использование:

# 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"
    "[email protected]"
}

Теперь я могу сделать:

$ 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
66
Mikel

Вы можете держать заголовок вверху вот так с помощью bash:

command | (read -r; printf "%s\n" "$REPLY"; sort)

Или сделайте это с Perl:

command | Perl -e 'print scalar (<>); print sort { ... } <>'
41
Andy

Я нашел хорошая версия awk , которая хорошо работает в скриптах:

awk 'NR == 1; NR > 1 {print $0 | "sort -n"}'
30
Michael Kuhn

Хакерский, но эффективный: готовый 0 ко всем строкам заголовка и 1 ко всем остальным строкам перед сортировкой. Снимите префикс после сортировки.

… |
awk '{print (NR <= 2 ? "0 " : "1 ") $0}' |
sort -k 1 -k… |
cut -b 3-
5
Gilles 'SO- stop being evil'

Вот некоторый волшебный шум строки Perl, через который вы можете направить вывод, чтобы отсортировать все, но оставить первую строку вверху: Perl -e 'print scalar <>, sort <>;'

4
Ryan C. Thompson

Я попробовал command | {head -1; sort; } и ​​может подтвердить, что на самом деле все портит --head читает несколько строк из канала, а затем выводит только первую. Таким образом, остальная часть вывода, которую head не прочитала , передается sort-- НЕ остальным вывода, начиная со строки 2!

В результате вы пропускаете строки (и одну частичную строку!), Которые были в начале вывода вашей команды (за исключением того, что у вас еще есть первая строка) - факт, который легко подтвердить, добавив канал в wc в конце вышеупомянутого конвейера - но это чрезвычайно трудно отследить, если вы этого не знаете! Я потратил не менее 20 минут, пытаясь понять, почему у меня была неполная строка (первые 100 байт или около того, обрезанная) в моем выводе, прежде чем ее решить.

То, что я в итоге сделал, что работало прекрасно и не требовало запуска команды дважды, было:

myfile=$(mktemp)
whatever command you want to run > $myfile

head -1 $myfile
sed 1d $myfile | sort

rm $myfile

Если вам нужно поместить вывод в файл, вы можете изменить это следующим образом:

myfile=$(mktemp)
whatever command you want to run > $myfile

head -1 $myfile > outputfile
sed 1d $myfile | sort >> outputfile

rm $myfile
2
Wildcard

Я думаю, что это проще всего.

ps -ef | ( head -n 1 ; sort )

или это, что, возможно, быстрее, поскольку он не создает суб Shell

ps -ef | { head -n 1 ; sort ; }

Другое крутое использование

перетасовать строки после строки заголовка

cat file.txt |  ( head -n 1 ; shuf )

обратные строки после строки заголовка

cat file.txt |  ( head -n 1 ; tac )
1
user2449151
command | head -1; command | tail -n +2 | sort
0
Sarva

Я пришел сюда в поисках решения для команды w. Эта команда показывает детали того, кто вошел в систему и что они делают.

Чтобы показать отсортированные результаты, но с верхними заголовками (есть две строки заголовков), я остановился на:

w | head -n 2; w | tail -n +3 | sort

Очевидно, что это запускает команду w дважды и поэтому может не подходить для всех ситуаций. Тем не менее, к его преимуществам это значительно легче запомнить.

Обратите внимание, что tail -n +3 означает "показать все строки начиная с 3-го года" (см. man tail для деталей).

0
Robert

Просто и понятно!

<command> | head -n 1; <command> | sed 1d | sort <....>
  • sed nd ---> 'n' указывает номер строки, а 'd' обозначает удаление.
0
Jatsui