Zsh は変数値に引用符を追加する可能性があります (ただし bash では動作します)

Zsh は変数値に引用符を追加する可能性があります (ただし bash では動作します)

私はzshを使い始めたばかりです(昨日bashから移行しました)

私はbashで次のようなbash関数を持っていました

vl() { cmd=`echo $1 | sed -r 's/(.+):([0-9]+).+/\1 +\2/g'`; vim $cmd }

これは基本的に次のような引数を変換します:

vl ./manifests/production/test.pp:387:foobar  # A output of $grep -iHn test 

vim ./manifests/production/test.pp +387   #Aim is to open file at line-number 387

zsh の同じ関数は期待どおりに動作しません。 が追加された名前のファイルを開くのではなく、vim で名前が付けられたファイルを開きます。./manifests/production/test.pp +387に引用符を追加しているようです。./manifests/production/test.pp+387$cmd

ここで何が起こっているのか誰か説明してくれると嬉しいです。ありがとう

答え1

Bourne シェル、dash、ksh、bash などの通常の Bourne スタイルのシェルでは、構文は$variable「変数の値を取得し、文字がIFS出現する個別の単語に分割し、各単語をファイル名のワイルドカード パターンとして扱い、1 つ以上のファイルに一致する場合は拡張する」ことを意味します。がvariable配列の場合、これは配列の最初の要素に対して行われ、他の要素は無視されます。

zsh では、構文は$variable「変数の値を取得するが、空の場合は削除する」という意味です。variable配列の場合は、配列のすべての要素に対してこれが行われます。zsh 愛好家は、zsh の方法が優れていると考えています。

$=variablezsh では、単語分割を実行するように記述できます。ただし、これは、実行しようとしていることを実行する最善の方法ではありません。bash 関数はファイル名の空白文字に対応しておらず、 $=variablezsh での使用も同様です。次に、bash と zsh の両方で機能し、:ファイル名以外の任意の文字に対応する、引数を解析する別の方法を示します。引数に 2 つのコロンが含まれている場合、最初のコロンの後のすべてが削除され、最初のコロンと 2 番目のコロンの間の部分が、先頭に符号が付いた別の引数として追加されます+。これは、コードより少し長くなりますが、理解しにくくはなく、ファイル名にスペースが少しでも含まれていても詰まることはありません。

vl () {
  local suffix
  case $1 in
    *:*:*) suffix=${1#*:};; set -- "${1%%:*}" "+${suffix%%:*}";;
  esac
  vim "$@"
}

答え2

これは難しい問題です :) 回避策の 1 つは、次のように関数を定義することです。

vl() { cmd=$(echo $1 | sed -r 's/(.+):([0-9]+).+/\1 +\2/g'); eval "vim $cmd"; }

回避策は を使用することでありeval、必要な StackExchange 編集スキルがないために行ったその他の小さな変更ではないことに注意してください 8-)

関連情報