Знакомство с упорядочиванием в Emacs на примерах

в 10:00, , рубрики: elisp, emacs, ruvds_перевод, UNIX, редактор, упорядочивание в emacs

Знакомство с упорядочиванием в Emacs на примерах - 1


В этой статье мы разберём использование в 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 и постами о ретроиграх 🕹️

Автор: Дмитрий Брайт

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js