Есть ли способ, чтобы игнорировать строки заголовка в каком-то ЮНИКСЕ?


у меня есть файл с фиксированной шириной поля, который я пытаюсь отсортировать с помощью утилиты сортировки UNIX (Cygwin, в моем случае).

проблема в том, что в верхней части файла есть двухстрочный заголовок, который сортируется в нижней части файла (поскольку каждая строка заголовка начинается с двоеточия).

есть ли способ сказать sort либо "передать первые две строки через несортированные", либо указать порядок, который сортирует строки двоеточия сверху - остальные строки всегда начинаются с a 6-значный числовой (который на самом деле является ключом, который я сортирую), если это поможет.

пример:

:0:12345
:1:6:2:3:8:4:2
010005TSTDOG_FOOD01
500123TSTMY_RADAR00
222334NOTALINEOUT01
477821USASHUTTLES21
325611LVEANOTHERS00

должен в:

:0:12345
:1:6:2:3:8:4:2
010005TSTDOG_FOOD01
222334NOTALINEOUT01
325611LVEANOTHERS00
477821USASHUTTLES21
500123TSTMY_RADAR00
11 72

11 ответов:

(head -n 2 <file> && tail -n +3 <file> | sort) > newfile

скобки создают подобласть, обертывая stdout, чтобы вы могли передать его или перенаправить, как если бы он пришел из одной команды.

если вы не возражаете против использования awk, вы можете воспользоваться awk встроенные способности трубы

например.

extract_data | awk 'NR<3{print ;next}{print | "sort -r"}' 

это печатает первые две строки дословно и трубы остальные через sort.

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

вот версия, которая работает на водопроводной данные:

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

Если ваш заголовок содержит несколько строк:

(for i in $(seq $HEADER_ROWS); do read -r; printf "%s\n" "$REPLY"; done; sort)

это решение от здесь

можно использовать tail -n +3 <file> | sort ... (хвост будет выводить содержимое файла из 3-й строки).

head -2 <your_file> && nawk 'NR>2' <your_file> | sort

пример:

> cat temp
10
8
1
2
3
4
5
> head -2 temp && nawk 'NR>2' temp | sort -r
10
8
5
4
3
2
1

Это займет всего 2 строки кода...

head -1 test.txt > a.tmp; 
tail -n+2 test.txt | sort -n >> a.tmp;

для числовых данных требуется-n. Для Альфа-сортировки-n не требуется.

пример файла:
$ кошачий тест.txt

заголовок
8
5
100
1
-1

результат:
$ коту.ТМП

заголовок
-1
1
5
8
100

С Python:

import sys
HEADER_ROWS=2

for _ in range(HEADER_ROWS):
    sys.stdout.write(next(sys.stdin))
for row in sorted(sys.stdin):
    sys.stdout.write(row)

вот функция оболочки bash, полученная из других ответов. Он обрабатывает как файлы, так и трубы. Первый аргумент-это имя файла или '-' для ввода. Остальные аргументы передаются для сортировки. Пара примеров:

$ hsort myfile.txt
$ head -n 100 myfile.txt | hsort -
$ hsort myfile.txt -k 2,2 | head -n 20 | hsort - -r

функция Shell:

hsort ()
{
   if [ "" == "-h" ]; then
       echo "Sort a file or standard input, treating the first line as a header.";
       echo "The first argument is the file or '-' for standard input. Additional";
       echo "arguments to sort follow the first argument, including other files.";
       echo "File syntax : $ hsort file [sort-options] [file...]";
       echo "STDIN syntax: $ hsort - [sort-options] [file...]";
       return 0;
   elif [ -f "" ]; then
       local file=;
       shift;
       (head -n 1 $file && tail -n +2 $file | sort $*);
   elif [ "" == "-" ]; then
       shift;
       (read -r; printf "%s\n" "$REPLY"; sort $*);
   else
       >&2 echo "Error. File not found: ";
       >&2 echo "Use either 'hsort <file> [sort-options]' or 'hsort - [sort-options]'";
       return 1 ;
   fi
}

Это то же самое, что и ответ Яна Щербина, но моя реализация :-

cut -d'|' -f3,4,7 $arg1 | uniq > filetmp.tc
head -1 filetmp.tc > file.tc;
tail -n+2 filetmp.tc | sort -t"|" -k2,2 >> file.tc;

Итак, вот функция bash, где аргументы точно такие же, как сортировка. Поддержка файлов и каналов.

function skip_header_sort() {
    if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then
        local file=${@: -1}
        set -- "${@:1:$(($#-1))}"
    fi
    awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file
}

как это работает. Эта строка проверяет, есть ли хотя бы один аргумент и является ли последний аргумент файлом.

    if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then

это сохраняет файл в отдельную аргумент. Так как мы собираемся стереть последний аргумент.

        local file=${@: -1}

здесь мы удаляем последний аргумент. Поскольку мы не хотим передавать его как аргумент сортировки.

        set -- "${@:1:$(($#-1))}"

наконец, мы делаем часть awk, передавая аргументы (минус последний аргумент, если это был файл) для сортировки в awk. Это было первоначально предложено Дэйвом и изменено, чтобы принять аргументы сортировки. Мы полагаемся на то, что $file будет пуст, если мы трубопроводы, таким образом, игнорируется.

    awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file

пример использования с файлом, разделенным запятой.

$ cat /tmp/test
A,B,C
0,1,2
1,2,0
2,0,1

# SORT NUMERICALLY SECOND COLUMN
$ skip_header_sort -t, -nk2 /tmp/test
A,B,C
2,0,1
0,1,2
1,2,0

# SORT REVERSE NUMERICALLY THIRD COLUMN
$ cat /tmp/test | skip_header_sort -t, -nrk3
A,B,C
0,1,2
2,0,1
1,2,0
cat file_name.txt | sed 1d | sort 

Это будет делать то, что вы хотите.