2012-01-13 2 views
3

私は次の行入れたい:シェルスクリプトに

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

を、私はこの長いと複雑なライン毎回書く必要がいけません。それがあるように私は私のシェルスクリプトにそれを置くときしかし、私はエラーを取得:

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

私はここに"エスケープ問題のいくつかの並べ替えがあると思いますし、私はこの行でいくつかの\を配置する必要があります。何を修正する必要がありますか?

答えて

7

これは正常です。文字列は一重引用符で囲まれ、変数は一重引用符では展開されません。

あなたは彼らが展開されますように、二重引用符を使用し、文字列内の既存の二重引用符をエスケープする必要があります

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

それは変数を展開するときに、だけ外側の引用符がを重要であることは注目に値します。つまり:

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

'foo'と表示されます。単一引用符がここでは$Aを囲むという事実は重要ではありません。外側の引用符は二重引用符です。

5

直ちに問題になるのは、一重引用符がシェルによるすべての展開を妨げることです。あらゆる種類の拡張が起こるには、二重引用符が必要です。しかし、emacs --eval "(ediff \"$1\" \"$2\")"と書くことはできません。なぜなら、ファイル名にはEmacsが正しく引用符で囲まれないため、ファイル名に"または\が含まれているとスクリプトが壊れてしまうからです。

幸いなことに、非常に簡単な解決策があります:

emacs --eval '(ediff command-line-args-left)' "[email protected]" 

emacsclientを呼び出すことによって、存在する場合既存のEmacsプロセスを再利用する方が良いだろう。残念ながら、Emacsclientでは、--evalはすべての引数をLisp式として扱います。だから、シェルの中で引用符を使う必要があります。 bashまたはkshでは、二重引用符とバックスラッシュの前にバックスラッシュを追加するのに${VARIABLE//PATTERN/REPLACEMENT}を使用できます。それは少し痛いですが、それは動作します。

quoted1=${1//\\/\\\\}; quoted1=${quoted1//\"/\\\"} 
quoted2=${2//\\/\\\\}; quoted2=${quoted2//\"/\\\"} 
emacsclient -a '' --eval "(ediff \"$quoted1\" \"$quoted2\")" 
+0

:私は、フォールバックの編集者としてのemacsclientとemacsのための-c引数を追加しました。私は file1 = $(readlink -f $ 1)を追加しました file2 = $(readlink -f $ 2) とediffは$ file1と$ file2を読み込みます – Lalylulelo

0

私は2つのヒントを組み合わせた、私の$HOME/.profileに「ediff」と呼ばれる簡単な機能を有しています。 Gilles abovedefunitive blogの1つです。私はそれらを読むためにediffためには絶対パスでファイルを交換する必要があり、私にはわからない理由で、

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 
} 
関連する問題