3

次のシェルスクリプトは、引数のリストを取得し、UnixパスをWINE / Windowsパスに変換し、WINEで指定された実行可能ファイルを呼び出します。

#! /bin/sh

if [ "${1+set}" != "set" ]
then 
  echo "Usage; winewrap EXEC [ARGS...]"
  exit 1
fi

EXEC="$1"
shift

ARGS=""

for p in "$@";
do
  if [ -e "$p" ]
  then
    p=$(winepath -w $p)
  fi
  ARGS="$ARGS '$p'"
done

CMD="wine '$EXEC' $ARGS"
echo $CMD
$CMD

ただし、コマンドライン引数の引用には問題があります。

$ winewrap '/home/chris/.wine/drive_c/Program Files/Microsoft Research/Z3-1.3.6/bin/z3.exe' -smt /tmp/smtlib3cee8b.smt
Executing: wine '/home/chris/.wine/drive_c/Program Files/Microsoft Research/Z3-1.3.6/bin/z3.exe' '-smt' 'Z: mp\smtlib3cee8b.smt'
wine: cannot find ''/home/chris/.wine/drive_c/Program'

ご了承ください:

  1. 実行可能ファイルへのパスは、一重引用符で囲まれていますが、最初のスペースで切り取られています。
  2. 最後のパスのリテラル「\t」はタブ文字に変換されています。

明らかに、引用符はシェルが意図した方法で解析されていません。これらのエラーを回避するにはどうすればよいですか?

編集:「\ t」は、2つのレベルの間接参照によって拡張されています。最初に、"$p"(および/または)が;"$ARGS"に拡張されています。Z:\tmp\smtlib3cee8b.smt次に、\tタブ文字に展開されます。これは(一見)同等です

Y='y\ty'
Z="z${Y}z"
echo $Z

これは

zy\tyz

ではなく

zy  yz

更新:eval "$CMD"トリックを行います。" \t"問題はechoの障害のようです: "最初のオペランドが-nの場合、またはいずれかのオペランドに円記号('\')文字が含まれている場合、結果は実装定義です。" (のPOSIX仕様echo

4

4 に答える 4

3
  • bash の配列は移植できませんが、シェルで引数リストを処理する唯一の適切な方法です
  • 引数の数は ${#} です
  • 現在のディレクトリにダッシュで始まるファイル名がある場合、スクリプトで悪いことが起こります
  • スクリプトの最後の行がプログラムを実行するだけで、終了時にトラップがない場合は、それを実行する必要があります

それを念頭に置いて

#! /bin/bash

# push ARRAY arg1 arg2 ...
# adds arg1, arg2, ... to the end of ARRAY
function push() {
    local ARRAY_NAME="${1}"
    shift
    for ARG in "${@}"; do
        eval "${ARRAY_NAME}[\${#${ARRAY_NAME}[@]}]=\${ARG}"
    done
}

PROG="$(basename -- "${0}")"

if (( ${#} < 1 )); then
  # Error messages should state the program name and go to stderr
  echo "${PROG}: Usage: winewrap EXEC [ARGS...]" 1>&2
  exit 1
fi

EXEC=("${1}")
shift

for p in "${@}"; do
  if [ -e "${p}" ]; then
    p="$(winepath -w -- "${p}")"
  fi
  push EXEC "${p}"
done

exec "${EXEC[@]}"
于 2008-09-21T23:35:25.980 に答える
1

私はあなたが使用すべきCMDへの割り当てをしたいです

eval $CMD

$CMDスクリプトの最後の行の代わりに。これにより、パス内のスペースに関する問題が解決されるはずです。「\ t」の問題についてどうすればよいかわかりません。

于 2008-09-03T16:02:40.363 に答える
0

次のように、スペースの前に\を付けることができます。

/home/chris/.wine/drive_c/Program Files/Microsoft\ Research/Z3-1.3.6/bin/z3.exe

\tの問題でも同じことができます-\\tに置き換えてください。

于 2008-08-30T16:42:34.670 に答える
0

$CMDの最後の行を

ワイン'$EXEC' $ ARGS

エラーは「/home/chris/.wine/drive_c/Program」ではなく「/home/chris/.wine/drive_c/Program」であることに注意してください。

一重引用符が適切に補間されておらず、文字列がスペースで分割されています。

于 2008-08-30T17:37:17.800 に答える