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 風格 shell 中,例如 Bourne shell、dash、ksh 和 bash,語法的$variable意思是「獲取變數的值,將其拆分為IFS出現字元的單獨單詞,並將每個單字視為檔案名稱通配符模式,並且如果它與多個文件之一匹配,則展開它」。如果variable是數組,則這種情況發生在數組的第一個元素上,而其他元素將被忽略。

在 zsh 中,語法的$variable意思是「取得變數的值,如果它為空則將其刪除」。如果variable是一個數組,則該數組的所有元素都會發生這種情況。 Zsh 愛好者認為 zsh 方式更優越。

在 zsh 中,您可以編寫$=variable來執行分詞。不過,這並不是做你正在做的事情的最佳方式。您的 bash 函數無法處理檔案名稱中的空格,並且$=variable在 zsh 中使用也不會。這是一種不同的解析參數的方法,它適用於 bash 和 zsh,並且可以處理除:檔案名稱之外的任何字元。如果參數包含兩個冒號,則刪除第一個冒號之後的所有內容,並將第一個冒號和第二個冒號之間的部分作為單獨的參數附加,前面加一個+符號。它比您的程式碼稍長,但不那麼難以理解,而且它不會因為檔案名稱中的第一個空格提示而感到窒息。

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

答案2

這是一個棘手的問題:) 一種解決方法是像這樣定義函數:

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

請注意,解決方法是使用eval,而不是我必須做的其他小修改,因為我缺少所需的 stackexchange editor-fu 8-)

相關內容