ksh плохой […] синтаксис не приводит к ошибке - PullRequest
2 голосов
/ 20 октября 2011

Я только что нашел следующий код в сценарии ksh:

  if [ "${file_id}" = "0" ] || [ "${file_id}" = "100" ] || "${file_id}" = "100" ]
  then
    # Do some stuff
  fi

Обратите внимание, в частности, на пропущенную [ перед третьей ${file_id}.

Я рад, что это не очень приятный синтаксис, даже без этой ошибки, и что [[ … ]] обычно предпочтительнее, чем [ … ] в ksh.

Однако этот код выполняется полностью, как требуется, и ksh -n вообще не возражает против вышесказанного. Почему вышеупомянутое не терпит неудачу?

Ответы [ 2 ]

2 голосов
/ 01 ноября 2011

if [ "${file_id}" = "0" ] || [ "${file_id}" = "100" ] || "${file_id}" = "100" ]

Эта команда выполняется слева направо. Если эта команда обнаружила, что значение file_id равно 0, она не будет проверять следующие условия, поскольку эти условия разделяются оператором or. Если и 1-е, и 2-е условия не будут выполнены, он попытается проверить 3-е условие, и оно не будет выполнено.

file_id=1000
if [ "${file_id}" = "0" ] || [ "${file_id}" = "100" ] || "${file_id}" = "100" ]
then
echo "Exicuted for file_id=$file_id"
fi


ksh: 1000:  not found.
1 голос
/ 20 октября 2011

Мое первое предположение состоит в том, что это будет выполняться правильно с большинством (или всеми) оболочками типа Bourne , пока первое выражение оценивает значение true.Это ожидаемое поведение, поскольку && и || фактически закорачивают выполнение: т. Е. В a || b часть b не оценивается, если a истинно.

Примите во внимание следующее:

% for sh in ash bash ksh zsh;do

 printf 'running %s with id %d\n\n' "$sh" 0
 "$sh" -c 'file_id=0;[ "${file_id}" -eq 0 ] || oops'

done
running ash with id 0

running bash with id 0

running ksh with id 0

running zsh with id 0


% for sh in ash bash ksh zsh;do

  printf 'running %s with id %d\n\n' "$sh" 1
 "$sh" -c 'file_id=1;[ "${file_id}" -eq 0 ] || oops'

done
running ash with id 1

ash: oops: not found
running bash with id 1

bash: oops: command not found
running ksh with id 1

ksh: oops: not found
running zsh with id 1

zsh:1: command not found: oops

Более того, вы не можете набирать то, что хотите, в правой части короткозамкнутого выражения, потому что синтаксический анализатор попытается проанализировать всю строку, прежде чем выполнить ее (т. Е. Потерял место метасимвол вызовет ошибку)

% ksh -c 'id=0; [ "$id" -eq 0 ] || )' 
ksh: syntax error: ')' unexpected

Обратите также внимание, что до тех пор, пока выполнение команды (встроенной или внешней) откладывается, оболочка не может знать, является ли она действительной или нет.Напротив, синтаксис зарезервированных слов оболочки и позиции метасимволов известны во время разбора:

% ksh -c 'type [ [[;id=0; [ "$id" -eq 0 ] || [[ '
ksh: syntax error: unexpected EOF
% ksh -c 'type [ [[;id=0; [ "$id" -eq 0 ] || [ ' 
[ is a shell builtin
[[ is a reserved word
...