В этой статье мы разберём использование в Emacs различных команд для упорядочивания строк, абзацев и страниц. В руководствах к Emacs и Elisp эти команды описаны достаточно подробно, так что мы просто познакомимся с практическими примерами их применения.
▍ Упорядочивание строк
В первой серии примеров мы рассмотрим различные способы упорядочивания строк. Для этого вам нужно будет проследовать описанным ниже шагам.
1. Создайте буфер со следующим текстом:
Carol 200 London LHR->SFO
Dan 20 Tokyo HND->LHR
Bob 100 London LCY->CDG
Alice 10 Paris CDG->LHR
Bob 30 Paris ORY->HND
Представим, что каждая строка – это запись, содержащая некую информацию о разных людях. Слева направо в ней указаны имя человека, его численный ID, текущее местонахождение и планируемое направление путешествия. Например, в первой строке указано, что Кэрол, находясь в Лондоне, планирует отправиться из аэропорта London Heathrow (LHR) в Сан-Франциско (SFO).
2. Введите
C-x h
, чтобы отметить весь буфер, и M-x sort-lines RET
для упорядочивания строк по алфавиту. В результате его содержимое будет выглядеть так:Alice 10 Paris CDG->LHR
Bob 100 London LCY->CDG
Bob 30 Paris ORY->HND
Carol 200 London LHR->SFO
Dan 20 Tokyo HND->LHR
3. Введите команду
C-x h
, сопровождаемую C-u M-x sort-lines RET
, чтобы реверсировать алфавитное упорядочивание строк. Комбинация C-u
задаёт префиксный аргумент, который указывает на необходимость выполнения обратного упорядочивания. Теперь содержимое буфера выглядит так:Dan 20 Tokyo HND->LHR
Carol 200 London LHR->SFO
Bob 30 Paris ORY->HND
Bob 100 London LCY->CDG
Alice 10 Paris CDG->LHR
4. Введите
C-x h
, сопровождаемую M-x sort-fields RET
, чтобы упорядочить строки только по их первым полям. Поля разделяются пробелом. Заметьте, что полученный результат немного отличается от результата M-x sort-lines RET
из пункта 2. Здесь Боб из Парижа перечислен до Боба из Лондона, потому что упорядочивание было произведено только по первому полю. Остальную часть каждой строки алгоритм проигнорировал. А вот в пункте 2 Боб из Лондона шёл до Боба из Парижа, потому что упорядочивание выполнялось с учётом строк целиком.Alice 10 Paris CDG->LHR
Bob 30 Paris ORY->HND
Bob 100 London LCY->CDG
Carol 200 London LHR->SFO
Dan 20 Tokyo HND->LHR
5. Введите
C-x h
, сопровождаемую M-2 M-x sort-fields RET
, чтобы упорядочить строки по второму полю в алфавитном порядке. Комбинация M-2
задаёт численный аргумент, указывающий номер поля, по которому нужно упорядочить строки. Заметьте, что значение 100 оказалось выше 20, потому что сортировка производилась по алфавиту, а не по числам. Вот результат:Alice 10 Paris CDG->LHR
Bob 100 London LCY->CDG
Dan 20 Tokyo HND->LHR
Carol 200 London LHR->SFO
Bob 30 Paris ORY->HND
6. Введите
C-x h
, сопровождаемую M-2 M-x sort-numeric-fields RET
, чтобы упорядочить строки по второму полю, но теперь в числовом порядке. Результат:Alice 10 Paris CDG->LHR
Dan 20 Tokyo HND->LHR
Bob 30 Paris ORY->HND
Bob 100 London LCY->CDG
Carol 200 London LHR->SFO
7. Введите
C-x h
, сопровождаемую M-3 M-x sort-fields RET
, чтобы упорядочить строки по третьему полю в алфавитном порядке. Результат:Bob 100 London LCY->CDG
Carol 200 London LHR->SFO
Alice 10 Paris CDG->LHR
Bob 30 Paris ORY->HND
Dan 20 Tokyo HND->LHR
Обратите внимание, что в этой команде мы не можем указать префиксный аргумент
C-u
для выполнения обратного упорядочивания, потому что здесь этот аргумент используется для обозначения поля, по которому нужно выполнить сортировку. Если же мы этот аргумент укажем, то он будет рассматриваться как численный аргумент 4, и сортировка будет произведена по четвёртому полю. Тем не менее обратное упорядочивание по определённому полю всё же выполнить можно, и в следующем пункте показано, как это сделать.8. Введите
C-x h
, сопровождаемую M-x reverse-region RET
. В сочетании с предыдущей командой эта, по сути, реверсирует упорядочивание строк по названиям городов. Вот результат:Dan 20 Tokyo HND->LHR
Bob 30 Paris ORY->HND
Alice 10 Paris CDG->LHR
Carol 200 London LHR->SFO
Bob 100 London LCY->CDG
9. Введите
C-x h
, сопровождаемую M-- M-2 M-x sort-fields RET
, чтобы упорядочить строки по второму полю справа (третье слева) в алфавитном порядке. Заметьте, что первые две комбинации клавиш – это meta+-
и meta+2
. Отрицательный аргумент -2
обуславливает упорядочивание строк по второму полю справа. Вот результат:Carol 200 London LHR->SFO
Bob 100 London LCY->CDG
Bob 30 Paris ORY->HND
Alice 10 Paris CDG->LHR
Dan 20 Tokyo HND->LHR
10. Введите
M-<
, чтобы перенести точку (курсор) в начало буфера. Затем введите C-s London RET
, сопровождаемую M-b
, чтобы перенести точку в начало слова London в первой строке. Теперь введите C-SPC
, чтобы установить там отметку.Далее введите
C-4 C-n C-e
, чтобы переместить точку в конец последней строки. В итоге в буфере будет представлена активная область.Наконец, введите
M-x sort-columns RET
, чтобы упорядочить столбцы, ограниченные положениями метки и точки (то есть последние два). Вот результат:Bob 100 London LCY->CDG
Carol 200 London LHR->SFO
Alice 10 Paris CDG->LHR
Bob 30 Paris ORY->HND
Dan 20 Tokyo HND->LHR
11. Как и прежде, введите
M-<
, чтобы перенести точку к началу буфера. Затем введите C-s London RET
, сопровождаемую M-b
, чтобы поместить её в начало слова London на первой строке. Установите здесь отметку с помощью C-SPC
.Далее введите
C-4 C-n C-e
, чтобы перенести точку в конец последней строки. В буфере снова будет отражена активная область.Введите
C-u M-x sort-columns RET
, чтобы отсортировать последние два столбца в обратном порядке.Dan 20 Tokyo HND->LHR
Bob 30 Paris ORY->HND
Alice 10 Paris CDG->LHR
Carol 200 London LHR->SFO
Bob 100 London LCY->CDG
12. Внимание: в этом шаге показано, как не нужно использовать команду
sort-regexp-fields
. В большинстве случаев вы наверняка этого делать не станете. В пункте ниже описано типичное использование команды, подходящее в большинстве ситуаций.Введите
C-x h
, сопровождаемую M-x sort-regexp-fields RET [A-Z]*->\(.*\) RET \1 RET
, чтобы упорядочить строки по аэропорту места назначения. Эта команда, используя группу регулярного выражения (\(.*\)
), сначала сопоставляет целевой аэропорт в каждой строке. Затем мы просим эту команду упорядочить совпавшие с группой поля и получаем:Dan 20 Tokyo LCY->CDG
Bob 30 Paris ORY->HND
Alice 10 Paris HND->LHR
Carol 200 London CDG->LHR
Bob 100 London LHR->SFO
В итоге все записи смешались. Теперь Дэн из Токио путешествует из LCY в CDG, а не из HND в LHR. Сравните эти результаты с результатами из предыдущего пункта. Данная команда правильно упорядочила поля места назначения и сохранила связь между аэропортом отправки и целевым аэропортом. Но связь между остальными полями (первые три столбца) и последним (аэропорт отправки и прибытия) оказалась нарушена. Это произошло, потому что регулярное выражение сопоставлялось только с последним столбцом, и упорядочивание было выполнено только с полем места назначения, в результате чего поля в последнем столбце сохранились без изменений, а остальная связь нарушилась.
В ходе сортировки перемещается только та часть каждой строки, которая соответствует регулярному выражению. Всё остальное остаётся без изменений. Это поведение может быть кстати в некоторых ситуациях, но в большинстве случаев нам нужно сохранять связь между всеми полями неизменной. Как это сделать, показано в следующем пункте.
Теперь введите
C-/
(или C-x u
), чтобы отменить эти изменения и вернуть буфер к прежнему состоянию, в котором он находился в конце предыдущего пункта.13. Предполагая, что состояние буфера соответствует результату пункта 11, мы рассмотрим, как изменить предыдущий шаг так, чтобы при упорядочивании строк по полю места назначения они все перемещались вместе с этим полем. Смысл в том, чтобы регулярное выражение сопоставлялось со всей строкой целиком. Для этого мы внесём в него небольшое изменение.
Введите
C-x h
, сопровождаемую M-x sort-regexp-fields RET .*->\(.*\) RET \1 RET
.Bob 100 London LCY->CDG
Bob 30 Paris ORY->HND
Dan 20 Tokyo HND->LHR
Alice 10 Paris CDG->LHR
Carol 200 London LHR->SFO
Теперь строки упорядочены по полю места назначения, и Дэн, находясь в Токио, планирует перелёт из HND в LHR.
14. Введите
C-x h
, сопровождаемую M-- M-x sort-regexp-fields RET .*->\(.*\) RET \1 RET
, чтобы реверсировать упорядочивание строк по целевому аэропорту. Заметьте, что первой комбинацией клавиш выступает meta+-
. Она задаёт отрицательный аргумент, обуславливающий сортировку в обратном порядке. Вот результат:Carol 200 London LHR->SFO
Dan 20 Tokyo HND->LHR
Alice 10 Paris CDG->LHR
Bob 30 Paris ORY->HND
Bob 100 London LCY->CDG
15. Наконец, обратите внимание, что для области также можно выполнять команды оболочки, заменяя её содержимое полученным результатом. Для демонстрации примера сначала нужно подготовить буфер. Введите
M-<
, сопровождаемую C-k C-k C-y C-y
, чтобы продублировать первую его строку.Теперь введите
C-x h
, сопровождаемую C-u M-| sort -u
, чтобы упорядочить строки, удалив при этом повторы. Последовательность M-|
вызывает команду shell-command-on-region
, которая запрашивает команду оболочки, выполняет её и отображает результат в области вывода. Если результат в эту область не входит, он выводится в отдельном буфере. Тем не менее, если указать префиксный аргумент, например с помощью
C-u
, содержимое области будет заменено выводом. В результате теперь наш буфер выглядит так:Alice 10 Paris CDG->LHR
Bob 100 London LCY->CDG
Bob 30 Paris ORY->HND
Carol 200 London LHR->SFO
Dan 20 Tokyo HND->LHR
Удалить повторы при сортировке можно и ещё одним способом: ввести
C-x h
, сопровождаемую M-x sort-lines RET
, а затем C-x h
, сопровождаемую M-x delete-duplicate-lines
. Также имейте в виду, что для области можно выполнять произвольные команды оболочки.
▍ Упорядочивание абзацев и страниц
Мы разобрали большинство команд, перечисленных в руководстве Emacs, и далее познакомимся ещё с несколькими. Теперь мы будем упорядочивать уже не отдельные строки, а абзацы и страницы.
1. Создайте буфер с приведённым ниже содержимым. Заметьте, что в этом тексте присутствует три символа перевода страницы. В Emacs эти символы обычно представлены как
^L
. В большинстве браузеров они, как правило, не отображаются. Символы ^L
, которые мы видим в тексте ниже, я наложил с помощью CSS, но рядом с ними реально присутствуют символы перевода страницы. Если вы читаете статью в одном из современных достойных браузеров, то можете скопировать текст в Emacs, где эти символы должны будут оказаться видны. Если же они не отобразятся, вставьте их сами с помощью комбинаций C-q C-l
.Emacs is an advanced, extensible, customizable,
self-documenting editor.
Emacs editing commands operate in terms of
characters, words, lines, sentences, paragraphs,
pages, expressions, comments, etc.
^L
We will use the term frame to mean a graphical
window or terminal screen occupied by Emacs.
At the very bottom of the frame is an echo area.
The main area of the frame, above the echo area,
is called the window.
^L
The cursor in the selected window shows the
location where most editing commands take effect,
which is called point.
If you are editing several files in Emacs, each in
its own buffer, each buffer has its own value of
point.
^L
2. В этом тексте шесть абзацев, заполняющих три страницы. Каждый символ перевода представляет конец страницы. Введите
C-x h
, сопровождаемую M-x sort-pages RET
, чтобы упорядочить страницы по алфавиту. Заметьте, что вторая страница перемещается вниз, потому что начинается с буквы «W». Теперь буфер будет выглядеть так:Emacs is an advanced, extensible, customizable,
self-documenting editor.
Emacs editing commands operate in terms of
characters, words, lines, sentences, paragraphs,
pages, expressions, comments, etc.
^L
The cursor in the selected window shows the
location where most editing commands take effect,
which is called point.
If you are editing several files in Emacs, each in
its own buffer, each buffer has its own value of
point.
^L
We will use the term frame to mean a graphical
window or terminal screen occupied by Emacs.
At the very bottom of the frame is an echo area.
The main area of the frame, above the echo area,
is called the window.
^L
3. Наконец, введите
C-x h
, сопровождаемую M-x sort-paragraphs
, чтобы упорядочить абзацы по алфавиту. Буфер изменится так:At the very bottom of the frame is an echo area.
The main area of the frame, above the echo area,
is called the window.
Emacs editing commands operate in terms of
characters, words, lines, sentences, paragraphs,
pages, expressions, comments, etc.
Emacs is an advanced, extensible, customizable,
self-documenting editor.
If you are editing several files in Emacs, each in
its own buffer, each buffer has its own value of
point.
The cursor in the selected window shows the
location where most editing commands take effect,
which is called point.
We will use the term frame to mean a graphical
window or terminal screen occupied by Emacs.
▍ Ссылки
Более подробно познакомиться с описанными командами можно в руководствах:
Для прочтения этих руководств введите в Emacs:
M-: (info "(emacs) Sorting") RET
M-: (info "(elisp) Sorting") RET
Кроме того, полезную информацию по этим командам также можно почитать в соответствующих строках документации. Для поиска этих строк используйте комбинацию
C-h f
. Например, введите C-h f sort-regexp-fields RET
, чтобы найти строку команды sort-regexp-fields
.Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх ????️
Rigidus
Еще более полезны все эти функции при работе в режиме org для сортировки таблиц. Полностью заменяет эксель например