#bash #sorting
#bash #сортировка
Вопрос:
У меня есть этот файл:
100: pattern1
1:pattern2
9:pattern2
79: pattern1
61: pattern1
и я хочу отсортировать его следующим образом:
1:pattern2
9:pattern2
61:pattern1
79:pattern1
100:pattern1
Возможно ли это только с помощью команды сортировки Linux?
Если бы у меня был :
4:pat1
3:pat2
2:pat2
1:pat1
O / p должен быть:
1:pat1
2:pat2
3:pat2
4:pat1
Итак, требуется выполнить сортировку по первой группе, но «группировать» по шаблону второй группы.
Пожалуйста, обратите внимание, что после: является шаблоном регулярного выражения, а не литералом.
Комментарии:
1. Каковы критерии для первой и второй группы?
2. Я понимаю, что вы пытаетесь сгруппировать строки в зависимости от того, что идет после ‘:’, и выводите разделительную строку между группами, но я не понимаю, как вы хотите, чтобы группы были отсортированы. Вы предполагаете, что диапазон числовых значений перед ‘:’ никогда не будет перекрываться между группами? То есть, если у вас есть «1: a», «2: b», «3: b» и «4: a», вы хотите получить «a» первыми или «b» первыми?
3. почему первая сотня попадает во вторую группу? Каковы критерии сортировки? По тексту, следующему за номером? значит, «1000: wow» войдет в 1-ю группу, а «1: это оно» — во вторую?
4. Похоже, вам было бы лучше вставить
s самостоятельно после просмотра каждой строки после сортировки, и вы видите, что значение после
:
изменилось.
Ответ №1:
Лучшее, что вы можете сделать, это отсортировать его в соответствии с числовыми значениями. Но вы ничего не можете сделать со строкой » «-.
$ sort -n input
1:wow
9:wow
61: this is it
79: this is it
100: this is it
Ответ №2:
Я не верю, что sort
один может сделать то, что вам нужно.
Создайте новый сценарий командной строки и поместите это в его содержимое (ie mysort.sh
):
#!/bin/sh
IFS=$'n' # This makes the for loop below split on newline instead of whitespace.
delim=
for l in `grep -v ^ | sort -g` # Ignore all lines and sort by number
do
current=`echo $l | sed s/^[0-9]*://g` # Get what comes after the number
if [ ! -z "$prev" ] amp;amp; [ "$prev" != "$current" ] # If it has changed...
then # then output a delimiter line.
echo $delim
fi
prev=$current
echo $l # Output this line.
done
Чтобы использовать его, передайте содержимое вашего файла следующим образом:
cat input | sh mysort.sh
Ответ №3:
Вероятно, нет — это не тот формат, который ожидает sort (1). И если бы вы это сделали, это был бы один из тех удивительных хаков, которые нелегко использовать. Если у вас есть какое-то правило для того, что находится между строками со знаками плюс, вы можете достаточно легко выполнить это с помощью скрипта AWK, Perl или Python.
Ответ №4:
Если ваш ввод был разделен пробелом, а не ‘:’:
sort -rk2 | uniq -D -f1
будет выполнять группировку;
- Я предполагаю, что вам нужно будет отсортировать «подразделы» позже (к сожалению, my
sort(1)
не выполняет упорядочение составных ключей. Я верю, что есть версии, которые позволяют вам делатьsort -k2,1n
, и вы бы закончили сразу). - используйте
--all-repeated=separate
вместо-D
, чтобы получить пустые разделители между группами. Посмотрите наman uniq
, чтобы узнать больше идей!
Однако, поскольку ваш ввод разделен двоеточием, требуется взлом:
sed 's/([0123456789] ):/1 /' t | sort -rk2 | uniq -D -f1
HTH