نقلا عن وسيطات سطر الأوامر في البرامج النصية قذيفة

StackOverflow https://stackoverflow.com/questions/36109

  •  09-06-2019
  •  | 
  •  

سؤال

التالية شيل يأخذ قائمة من الحجج ، يتحول Unix مسارات في النبيذ/ويندوز مسارات تحتج معين قابل للتنفيذ بموجب النبيذ.

#! /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"ويبدو أن المشكلة تكون صدى خطأ:"إذا كان المعامل الأول هو -ن ، أو إذا كان أي من المعاملات تحتوي على خط مائل عكسي ( '\' ) حرف, نتائج تنفيذ محددة." (مواصفات POSIX echo)

هل كانت مفيدة؟

المحلول

كنت تريد أن يكون تعيين إلى CMD يجب عليك استخدام

eval $CMD

بدلا من مجرد $CMD في السطر الأخير من السيناريو الخاص بك.هذا يجب أن تحل مشكلتك مع المساحات في مسارات أنا لا أعرف ما يجب القيام به حول " " المشكلة.

نصائح أخرى

  • باش المصفوفات هي unportable ولكن فقط عاقل طريقة للتعامل مع الحجة القوائم في قذيفة
  • عدد من الحجج في ${#}
  • الأشياء السيئة سوف يحدث مع السيناريو الخاص بك إذا كان هناك أسماء بدأت مع اندفاعة في الدليل الحالي
  • إذا كان السطر الأخير من السيناريو الخاص بك فقط يعمل البرنامج ، وليس هناك أي الفخاخ على الخروج ، يجب أن exec

مع أخذ ذلك في الاعتبار

#! /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/كريس/.النبيذ/drive_c/برنامج' وليس '/home/كريس/.النبيذ/drive_c/برنامج'

واحد يقتبس لم يتم محرف بشكل صحيح ، السلسلة يتم تقسيم المساحات.

يمكنك محاولة السابقة المساحات مع \ مثل ذلك:

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

يمكنك أيضا أن تفعل الشيء نفسه مع مشكلة استبدالها \ .

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top