У меня есть строка (или много строк) чисел, которые разделены произвольным символом. Какие инструменты UNIX я могу использовать для числовой сортировки элементов строки, сохраняя разделитель?
Примеры включают в себя:
- список номеров; вход
10 50 23 42
:; сортировать:10 23 42 50
- Айпи адрес; вход
10.1.200.42
:; сортировать:1.10.42.200
- CSV; вход
1,100,330,42
:; сортировать:1,42,100,330
- труба ограничена; вход
400|500|404
:; сортировать:400|404|500
Поскольку разделитель является произвольным, не стесняйтесь предоставлять (или расширять) Ответ, используя выбранный вами односимвольный разделитель.
sort
numeric-data
Джефф Шаллер
источник
источник
cut
поддерживает произвольные разделители с ее-d
опцией.4,325 comma 55 comma 42,430
не возникали и не возникали1.5 period 4.2
).Ответы:
Вы можете достичь этого с помощью:
замените точки
.
своим разделителем.Добавьте
-u
кsort
команде выше, чтобы удалить дубликаты.или с помощью
gawk
( GNUawk
) мы можем обработать много строк, в то время как вышеупомянутое также может быть расширено:замените
*
в качестве разделителя полейSEP='*'
свой разделитель .Примечания:
Вам может потребоваться использовать
-g, --general-numeric-sort
опциюsort
вместо,-n, --numeric-sort
чтобы обрабатывать любой класс чисел (целое число, число с плавающей запятой, научное, шестнадцатеричное и т. Д.).В
awk
отсутствии изменений потребности, она все равно будет обработка тех.источник
Использование
perl
есть очевидная версия; разделить данные, отсортировать их, снова объединить.Разделитель должен быть указан дважды (один раз в
split
и один раз вjoin
)например для
,
Так
Поскольку
split
это регулярное выражение, персонажу может потребоваться процитировать:При использовании
-a
и-F
возможности, можно удалить раскол. С помощью-p
цикла, как и раньше, и установите результаты на$_
, который автоматически выведет:источник
-l
опцию вместо использованияchomp
. Это также добавляет новую строку после печати. Смотрите также-a
(с-F
) разделительную часть.-l
и-F
, это еще лучше:perl -F'/\./' -le 'print join(".", sort {$a <=> $b} @F)'
-l
выбор; Я пропустил это!-F
флаг, потому что он не работает должным образом во всех версиях (например, ваша строка в CentOS 7 - perl 5.16.3 - возвращает пустой вывод, хотя он отлично работает в Debian 9). Но в сочетании с-p
этим дает немного меньший результат, поэтому я добавил это как альтернативу ответу. показывая, как-F
можно использовать. Благодарность!-a
и-n
параметры, когда-F
используется и-n
когда-a
используется ... так что просто перейдите-le
на-lane
Используя Python и идею, аналогичную ответу Стивена Харриса :
Так что-то вроде:
К сожалению, необходимость выполнять ввод / вывод вручную делает это гораздо менее элегантным, чем версия Perl.
источник
Bash скрипт:
Пример:
На основе
Разбить строку на массив в Bash
Как отсортировать массив в Bash
Объединить элементы массива?
источник
Ракушка
Загрузка языка более высокого уровня требует времени.
Для нескольких строк сама оболочка может быть решением.
Мы можем использовать внешнюю команду
sort
и командыtr
. Один из них достаточно эффективен для сортировки строк, а другой - для преобразования одного разделителя в новые строки:Это нужно bash из-за использования
<<<
только. Если это заменить на here-doc, решение действительно для posix.Это может сортировать поля с закладками, пробелами или оболочки Глобы символами (
*
,?
,[
). Не новые строки, потому что каждая строка сортируется.Перейдите
<<<"$2"
на<"$2"
обработку имен файлов и назовите их так:Разделитель одинаков для всего файла. Если это ограничение, оно может быть улучшено.
Однако для обработки всего 6000 строк требуется 15 секунд. По правде говоря, оболочка не лучший инструмент для обработки файлов.
Awk
Для более чем нескольких строк (более нескольких десятков) лучше использовать настоящий язык программирования. Решение awk может быть:
Что занимает всего 0,2 секунды для того же файла с 6000 строками, упомянутого выше.
Поймите, что
<"$2"
для файлов можно изменить обратно<<<"$2"
на строки внутри переменных оболочки.Perl
Самое быстрое решение - это Perl.
Если вы хотите отсортировать файл,
<<<"$a"
просто измените его"$a"
и добавьте-i
в perl параметры, чтобы сделать файл «на месте»:источник
Использование
sed
для сортировки октетов IP-адресаsed
не имеет встроеннойsort
функции, но если ваши данные достаточно ограничены в диапазоне (например, с IP-адресами), вы можете сгенерировать сценарий sed, который вручную реализует простую пузырьковую сортировку . Основной механизм заключается в поиске соседних номеров, которые не в порядке. Если числа не в порядке, меняйте их местами.Сам
sed
сценарий содержит две команды поиска и замены для каждой пары чисел с неупорядоченным порядком: одну для первых двух пар октетов (заставляя присутствовать конечный разделитель для обозначения конца третьего октета), и второй для третьей пары октетов (заканчивается EOL). Если происходит перестановка, программа переходит к началу скрипта, ища неупорядоченные числа. В противном случае это выходит.Сгенерированный скрипт, в частности:
Этот подход жестко кодирует точку как разделитель, который должен быть экранирован, так как в противном случае он будет «особенным» для синтаксиса регулярного выражения (допускает любой символ).
Чтобы сгенерировать такой скрипт sed, этот цикл будет делать:
Например, перенаправить вывод этого скрипта в другой файл
sort-ips.sed
.Примерный прогон может выглядеть так:
В следующем варианте генерирующего скрипта используются маркеры границы слова
\<
и\>
для избавления от необходимости второй замены. Это также сокращает размер сгенерированного сценария с 1,3 МБ до чуть менее 900 КБ, а также значительно сокращает время его выполненияsed
(примерно до 50% -75% от исходного, в зависимости от используемойsed
реализации):источник
sed
нелепо, поэтому это интересная задача.Вот некоторый bash, который угадывает сам разделитель:
Это может быть не очень эффективным и не чистым, но это работает.
Используйте как
bash my_script.sh "00/00/18/29838/2"
.Возвращает ошибку, когда один и тот же разделитель не используется последовательно или когда два или более разделителей следуют друг за другом.
Если используемый разделитель является специальным символом, он экранируется (в противном случае
sed
возвращается ошибка).источник
Этот ответ основан на неправильном понимании Q., но в некоторых случаях он в любом случае является правильным. Если входные данные являются полностью натуральными числами и имеют только один разделитель на строку (как в примере данных в Q), он работает правильно. Он также будет обрабатывать файлы со строками, каждый из которых имеет свой собственный разделитель, что немного больше, чем запрошено.
Эта функция оболочки
read
с от стандартного ввода, использует подстановку параметров POSIX , чтобы найти конкретный разделитель на каждой строке, (сохраненный в$d
), а также использует ,tr
чтобы заменить$d
с новой строки\n
иsort
˙s данные той линии, а затем восстанавливает первоначальные разделители каждой строки в:Применительно к данным, приведенным в ОП :
Выход:
источник
Для произвольных разделителей:
На входе вроде:
Это дает:
источник
Это должно обрабатывать любой нецифровый (0-9) разделитель. Пример:
Выход:
источник
С
perl
:С
ruby
, что несколько похоже наperl
Пользовательская команда и передача только строки-разделителя (не регулярное выражение). Будет работать, если на входе есть плавающие данные
Пользовательская команда для
perl
Дальнейшее чтение - у меня уже был этот удобный список однострочников perl / ruby
источник
Ниже приводится вариант ответа Джеффа в том смысле, что он генерирует
sed
сценарий, который будет выполнять сортировку пузыря, но достаточно отличается, чтобы оправдать свой собственный ответ.Разница в том, что вместо генерации O (n ^ 2) базовых регулярных выражений генерируется O (n) расширенных регулярных выражений. Полученный скрипт будет размером около 15 КБ. Время выполнения
sed
скрипта составляет доли секунды (генерация скрипта занимает немного больше времени).Он ограничен сортировкой положительных целых чисел, разделенных точками, но не ограничен размером целых чисел (просто увеличение
255
в основном цикле) или количеством целых чисел. Разделитель можно изменить, изменивdelim='.'
код.Это сделано для того, чтобы получить правильные выражения, поэтому я оставлю описание деталей на следующий день.
Сценарий будет выглядеть примерно так:
Идея сгенерированных регулярных выражений состоит в том, чтобы сопоставлять образцы для чисел, которые меньше, чем каждое целое число; эти два числа будут не в порядке, и поэтому поменяются местами. Регулярные выражения сгруппированы в несколько опций OR. Обратите пристальное внимание на диапазоны, добавленные к каждому элементу, иногда они есть
{0}
, то есть немедленно предшествующий элемент должен быть исключен из поиска. Параметры регулярного выражения слева направо сопоставляют числа, которые меньше заданного числа, на:Чтобы разобрать пример, возьмите
101
(с дополнительными пробелами для удобства чтения):Здесь первое чередование допускает числа от 100 до 100; второе чередование позволяет от 0 до 99.
Другой пример
154
:Здесь первый вариант позволяет от 150 до 153; вторая позволяет от 100 до 149, а последняя - от 0 до 99.
Тестирование четыре раза в цикле:
Выход:
источник
Разделение ввода на несколько строк
Используя
tr
, вы можете разделить ввод с помощью произвольного разделителя на несколько строк.Этот вход затем можно просмотреть
sort
(используя,-n
если вход является числовым).Если вы хотите сохранить разделитель в выходных данных, вы можете использовать
tr
снова, чтобы добавить разделитель обратно.например, используя пробел в качестве разделителя
cat input.txt | tr " " "\n" | sort -n | tr "\n" " "
вход:
1 2 4 1 4 32 18 3
выход:1 1 2 3 4 4 18 32
источник