emacs --eval '(ediff "$ 1" "$ 2")' как поместить эту строку в shell-скрипт? - PullRequest
3 голосов
/ 13 января 2012

Я хочу поместить следующую строку:

emacs --eval '(ediff "$1" "$2")'

в сценарий оболочки, поэтому мне не нужно каждый раз писать эту длинную и сложную строку.Однако, когда я помещаю его в свой скрипт оболочки как есть, я получаю сообщение об ошибке:

ediff-find-file: File `$1' does not exist or is not readable

Я предполагаю, что здесь есть какая-то проблема ", и мне нужно поставить \в этой строке.Что именно мне нужно исправить?

Ответы [ 3 ]

7 голосов
/ 13 января 2012

Это нормально, ваша строка заключена в одинарные кавычки, а переменные не раскрываются в одинарных кавычках.

Вы должны использовать двойные кавычки, чтобы они расширялись, и избегать существующих двойных кавычек в строке:

emacs --eval "(ediff \"$1\" \"$2\")"

Стоит отметить, что при расширении переменных имеют значение только внешние кавычки . То есть:

$ A=foo
$ echo "'$A'"

напечатает 'foo'. Тот факт, что одинарные кавычки окружают $A, здесь не имеет значения: внешние кавычки - это двойные кавычки.

5 голосов
/ 13 января 2012

Ваша непосредственная проблема заключается в том, что одинарные кавычки предотвращают любое расширение оболочки.Вам нужны двойные кавычки для любого расширения.Тем не менее, вы не можете просто написать emacs --eval "(ediff \"$1\" \"$2\")", потому что имена файлов не будут правильно заключены в кавычки для Emacs, поэтому ваш скрипт сломается, если имена файлов будут содержать " или \.

К счастью,очень простое решение:

emacs --eval '(ediff command-line-args-left)' "$@"

Было бы лучше повторно использовать существующий процесс Emacs, если он есть, путем вызова emacsclient.К сожалению, в Emacsclient --eval обрабатывает все свои аргументы как выражения Lisp.Так что вам нужно сделать цитату внутри оболочки.В bash или ksh вы можете использовать ${VARIABLE//PATTERN/REPLACEMENT} для добавления обратной косой черты перед двойными кавычками и обратной косой чертой;это немного больно, но это работает.

quoted1=${1//\\/\\\\}; quoted1=${quoted1//\"/\\\"}
quoted2=${2//\\/\\\\}; quoted2=${quoted2//\"/\\\"}
emacsclient -a '' --eval "(ediff \"$quoted1\" \"$quoted2\")"
0 голосов
/ 05 сентября 2016

Чтобы в моем $HOME/.profile была простая функция, называемая "ediff", я объединил два совета вместе. Один из Жиля выше и из несуществующего блога . Я добавил аргумент -c для emacsclient и emacs в качестве запасного редактора:

ediff () {
    if [ "X${2}" = "X" ]
    then
        echo "USAGE: ediff <FILE 1> <FILE 2>"
    else
        quoted1=${1//\\/\\\\};quoted1=${quoted1//\"/\\\"}
        quoted2=${2//\\/\\\\};quoted2=${quoted2//\"/\\\"}
        emacsclient -c -a emacs -e "(ediff \"$quoted1\" \"$quoted2\")"
    fi
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...