Фильтрация текста с помощью команды оболочки в Emacs

В vi [m] есть команда !, которая позволяет мне перенаправлять текст через команда оболочки - например, сортировка или отступ - и вернуть отфильтрованный текст обратно в буфер. Есть ли эквивалент в emacs?


person Rohit    schedule 15.10.2008    source источник
comment
Просто немного не по касательной, я думаю, что у Vim нет M- | эквивалент Emacs, Vim может заменять только область выводом оболочки; если вы не напишете для него собственную команду, я был немного разочарован.   -  person A. Blizzard    schedule 03.01.2020


Ответы (3)


Вы можете выбрать регион и набрать `C-u M- | command RET ', и он заменяет регион выводом команды в том же буфере из-за интерактивного аргумента префикса shell-command-on-region.

person link0ff    schedule 16.10.2008
comment
Юрта на победу. Голосовать за. Клянусь, каждый раз, когда мне кажется, что я начинаю знакомиться с этой программой, кто-то приходит и показывает мне, что я новичок. - person dmckee --- ex-moderator kitten; 16.10.2008
comment
Обычно, когда вам нужна функция в Emacs, есть вероятность, что она уже давно реализована. Так что лучше всего сначала прочитать документацию, а не изобретать велосипед;) - person link0ff; 16.10.2008
comment
Спасибо, юрта. К сожалению, мне не удалось найти никакой документации по этой функции. - person Rohit; 16.10.2008
comment
Rohit, вы можете найти его документацию в Emacs, открыв руководство по Emacs (C-h i d m Emacs RET') and looking for the command name in the index - i shell-command-on-region RET '. - person link0ff; 16.10.2008
comment
Это хорошо для использования perl pie для поиска и замены регулярных выражений, когда Emacs Regexp не совсем подходит для этого. C-u M-| perl -pi -e 's/pattern/replace/g' RET. Evil также поддерживает команду Vim для этого (:%!perl -pi -e ... RET). - person d11wtq; 18.05.2013

Я написал это несколько лет назад, это может вам помочь:

(defun generalized-shell-command (command arg)
  "Unifies `shell-command' and `shell-command-on-region'. If no region is
selected, run a shell command just like M-x shell-command (M-!).  If
no region is selected and an argument is a passed, run a shell command
and place its output after the mark as in C-u M-x `shell-command' (C-u
M-!).  If a region is selected pass the text of that region to the
shell and replace the text in that region with the output of the shell
command as in C-u M-x `shell-command-on-region' (C-u M-|). If a region
is selected AND an argument is passed (via C-u) send output to another
buffer instead of replacing the text in region."
  (interactive (list (read-from-minibuffer "Shell command: " nil nil nil 'shell-command-history)
                     current-prefix-arg))
  (let ((p (if mark-active (region-beginning) 0))
        (m (if mark-active (region-end) 0)))
    (if (= p m)
        ;; No active region
        (if (eq arg nil)
            (shell-command command)
          (shell-command command t))
      ;; Active region
      (if (eq arg nil)
          (shell-command-on-region p m command t t)
        (shell-command-on-region p m command)))))

Я нашел эту функцию очень полезной. Если вы сочтете это полезным, я предлагаю для удобства привязать его к какой-либо функциональной клавише, лично я использую F3:

(global-set-key [f3] 'generalized-shell-command)
person Greg Mattes    schedule 16.10.2008
comment
Отлично. Это действует так же, как и команда Джо C-k / pipe через оболочку. - person Barry Kelly; 21.09.2013

Позднее редактирование: насколько я ценю положительные отзывы, ответ Юрты - лучший вариант. И хитрость Грега лучше, чем моя.

Остальное я оставлю здесь, потому что это может чего-то стоить, но ...


M-x shell-command-on-region, который по умолчанию привязан к M-|.


Я вижу, что это не совсем то, о чем просил Рохит. Использование C-h f shell-command-on-region показывает, что желаемое поведение доступно в неинтерактивной версии команды (путем установки аргумента replace не равным нулю). Для этого мы должны написать оболочку.

Попробуйте это (загрузите его в *scratch* и запустите M-x eval-buffer, если он работает, скопируйте его в свой файл .emacs):

(defun shell-command-on-region-replace (start end command)
  "Run shell-command-on-region interactivly replacing the region in place"
  (interactive (let (string) 
         (unless (mark)
           (error "The mark is not set now, so there is no region"))
         ;; Do this before calling region-beginning
         ;; and region-end, in case subprocess output
         ;; relocates them while we are in the minibuffer.
         ;; call-interactively recognizes region-beginning and
         ;; region-end specially, leaving them in the history.
         (setq string (read-from-minibuffer "Shell command on region: "
                            nil nil nil
                            'shell-command-history))
         (list (region-beginning) (region-end)
               string)))
  (shell-command-on-region start end command t t)
  )

И обратите внимание, как я говорю в комментариях, это не очень-то уж и безумно. Но я думаю, что это работает.


Для читателей, не знающих, как выбрать регион:

  1. Переместите «точку» (текущую позицию курсора) в один конец области и используйте C-space, чтобы активировать «метку»
  2. Переместите точку на другой конец области
  3. Готово, вызовите команду
person dmckee --- ex-moderator kitten    schedule 15.10.2008
comment
Спасибо, я знаю об этом, но он дает мне отфильтрованный текст в отдельном буфере; он не заменяет оригинал. - person Rohit; 16.10.2008
comment
Я знаю, какое поведение vi вам нужно. Все еще ищу. - person dmckee --- ex-moderator kitten; 16.10.2008
comment
Интересно, что это не просто FAQ. Я постоянно использую эту функцию в vi (или vim); редактор без него становится ... менее интересным. - person Jonathan Leffler; 16.10.2008
comment
Я использую это поведение и в vi, но это не способ emacs, который, вероятно, состоял бы в том, чтобы определить режим, который знает, что вы хотите, и позволяет этому происходить автоматически. - person dmckee --- ex-moderator kitten; 16.10.2008
comment
Я буду использовать то, что предложила юрта :) - person Rohit; 16.10.2008
comment
Поскольку вы упомянули о выборе региона. C-x h выбирает весь буфер, что часто бывает полезно. Я просто использовал его в этом случае. - person Stéphane Gourichon; 09.07.2013
comment
Если вы случайно запустите shell-command-on-region без префикса C-u, вы все равно можете скопировать вывод команды из буфера *Messages*. - person MatthewD; 10.09.2015
comment
Это очень хорошо. Кто-нибудь знает, как использовать приставку C-u в злом режиме? - person Martin; 03.05.2019