문제

다음 셸 스크립트는 인수 목록을 가져와 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. 마지막 경로의 리터럴 " "는 탭 문자로 변환됩니다.

분명히 인용문은 쉘에서 의도한 대로 구문 분석되지 않습니다.이러한 오류를 방지하려면 어떻게 해야 합니까?

편집하다:" "는 두 가지 수준의 간접 참조를 통해 확장됩니다.첫 번째, "$p" (및/또는 "$ARGS")로 확대되고 있습니다. Z:\tmp\smtlib3cee8b.smt;그 다음에, \t 탭 문자로 확장되고 있습니다.이것은 (겉보기에) 다음과 같습니다.

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

이는 다음과 같은 결과를 낳습니다.

zy\tyz

그리고 ~ 아니다

zy  yz

업데이트: eval "$CMD" 트릭을 수행합니다."\t" 문제는 에코의 잘못인 것 같습니다."첫 번째 피연산자가 -n이거나 피연산자에 백 슬래시 ( '') 문자가 포함 된 경우 결과는 구현 정의됩니다." (POSIX 사양 echo)

도움이 되었습니까?

해결책

나는 당신이 사용해야 하는 CMD에 대한 할당을 갖고 싶습니다.

eval $CMD

그냥 대신에 $CMD 스크립트의 마지막 줄에.이렇게 하면 경로의 공백 문제가 해결될 것입니다. " " 문제에 대해 어떻게 해야 할지 모르겠습니다.

다른 팁

  • 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[@]}"

$CMD의 마지막 줄을 다음으로 바꾸세요.

와인 '$EXEC' $ARGS

오류는 '/home/chris/.wine/drive_c/Program'이 아니라 ''/home/chris/.wine/drive_c/Program'입니다.

작은따옴표가 제대로 보간되지 않고 문자열이 공백으로 분할됩니다.

다음과 같이 공백 앞에 \를 사용해 볼 수 있습니다.

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

문제에 대해서도 동일한 작업을 수행할 수 있습니다. 이를 \ 로 바꾸십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top