Я экспериментирую с сортировкой GNU и LC_COLLATE="en_US.UTF-8". У меня есть файл с именем «тест»:

1,0 1
10 2
1,0 3
10 4

С sort -k1,2, как и с простым sort test порядок не меняется:

$ sort -k1,2 test
1,0 1
10 2
1,0 3
10 4

Таким образом, sort считает, что «1,0» равно «10», вероятно, из-за некоторых особенностей LC_COLLATE (пропуск пунктуации?)

Теперь, когда я использую sort -k1,1 -k2,2, это дает мне другой порядок:

$ sort -k1,1 -k2,2 test
10 2
10 4
1,0 1
1,0 3

И внезапно sort больше не думает, что «10» — это то же самое, что «1,0».

Что случилось? Почему в данном случае sort -k1,1 -k2,2 не эквивалентно sort -k1,2? Это действительно должно быть эквивалентно? Или я неправильно истолковал справочную страницу? (Я пробовал версии 8.22 и 8.29 coreutils, обе имеют такое поведение)

2
lutyj 19 Июл 2018 в 19:23

1 ответ

Лучший ответ

-k1,2 означает «сортировать все строки, сравнивая одновременно содержимое всех полей с 1 по 2»; поэтому «1,0 1» сравнивается с «10 2» и т. д.

-k1,1 -k2,2 означает «сортировать все строки, сравнивая содержимое поля 1, а когда две строки имеют одинаковое содержимое в поле 1, сравнивая содержимое поля 2»; поэтому «1,0» сравнивается с «10», затем «2» с «4» и т. д.

То, что происходит затем, в обоих случаях сводится к сопоставлению, в частности к взвешиванию. Цифры обычно имеют больший вес, чем знаки препинания и пробелы. При сравнении «1,0 1» и «10 2» разница из-за запятой игнорируется, потому что цифры разные. При сравнении «1,0» и «10» единственная разница — это запятая, поэтому она больше не игнорируется. Подробнее см. ISO 14651.

Вы можете установить LC_COLLATE=C для сопоставления только на основе значений символов без веса. Оба ваших примера приводят к

1,0 1
1,0 3
10 2
10 4

Когда используется локаль «C».

2
Stephen Kitt 19 Июл 2018 в 20:00
Спасибо за объяснение. Это какие-то сложные правила сопоставления! Хорошо знать. На самом деле я использую LC_COLLATE=C локально, но при выполнении заданий в кластере Hadoop у меня нет такого же контроля над удаленными средами. Но это уже другой вопрос :)
 – 
lutyj
19 Июл 2018 в 19:52