LINUX.ORG.RU

История изменений

Исправление kalterfive, (текущая версия) :

Твой код фиксится до рабочего так:

$ a="watch \"\$(df -h |grep ^[/F];free -h|sed 's/  \*/ /g')|sed 8q\""
$ $a

Это конструкция $( ... ) (man 1 bash | grep 'Command Substitution'). Если использовать её, то на место первого аргумента bash подставит результат выполнения некоторой команды в этой конструкции. Если же её не использовать, то watch получит первым аргументом саму команду, а не результат её выполнения — об этом и говорит сообщение об ошибке в ПП.

Note: тем не менее, я не понимаю почему корректно работают конструкции с пайпом и eval-ом =)

Но суть проблемы я понял. Решение — испоьзовать массив вместо строки. Потому что bash может смотреть на исполняемое значение в строке так и только так:

  • "$a" — это одна команда, вне зависимости от предполагаемого количества аргументов, экранируемых символов, и т. д. ls /dev (например) — одна команда; ls — не команда, а /dev — не аргумент, но ls /dev — одна команда.
  • $a — bash всё-таки попытается отделить команду от аргументов и правильно их выполнить, но может ошибиться из-за пробелов:
    • a='ls arch' && $a == ls arch (здесь всё нормально);
    • a='ls "arch linux"' == ls \"arch linux\" (т. е. ls для директорий "arch и linux", но не для "arch linux");

Хинт: суть в том, что мы не можем достаточно (достаточно для корректности) точно задать команду в строке; во втором примере мы не можем указать начало и конец первого аргумента, bash это делает за нас. А для массива мы сможем точно задать команду и каждый аргумент в частности.

Исправление kalterfive, :

Твой код фиксится до рабочего так:

$ a="watch \"\$(df -h |grep ^[/F];free -h|sed 's/  \*/ /g')|sed 8q\""
$ $a

Это конструкция $( ... ) (man 1 bash | grep 'Command Substitution'). Если использовать её, то на место первого аргумента bash подставит результат выполнения некоторой команды в этой конструкции. Если же её не использовать, то watch получит первым аргументом саму команду, а не результат её выполнения — об этом и говорит сообщение об ошибке в ПП.

Note: тем не менее, я не понимаю почему корректно работают конструкции с пайпом и eval-ом =)

Но суть проблемы я понял. Решение — испоьзовать массив вместо строки. Потому что для массива мы сможем точно задать команду и каждый аргумент в частности. И потому что bash может смотреть на исполняемое значение в строке так и только так:

  • "$a" — это одна команда, вне зависимости от предполагаемого количества аргументов, экранируемых символов, и т. д. ls /dev (например) — одна команда; ls — не команда, а /dev — не аргумент, но ls /dev — одна команда.
  • $a — bash всё-таки попытается отделить команду от аргументов и правильно их выполнить, но может ошибиться из-за пробелов:
    • a='ls arch' && $a == ls arch (здесь всё нормально);
    • a='ls "arch linux"' == ls \"arch linux\" (т. е. ls для директорий "arch и linux", но не для "arch linux");

Хинт: суть в том, что мы не можем достаточно (достаточно для корректности) точно задать команду в строке; во втором примере мы не можем указать начало и конец первого аргумента, bash это делает за нас.

Исправление kalterfive, :

Твой код фиксится до рабочего так:

$ a="watch \"\$(df -h |grep ^[/F];free -h|sed 's/  \*/ /g')|sed 8q\""
$ $a

Это конструкция $( ... ) (man 1 bash | grep 'Command Substitution'). Если использовать её, то на место первого аргумента bash подставит результат выполнения некоторой команды в этой конструкции. Если же её не использовать, то watch получит первым аргументом саму команду, а не результат её выполнения — об этом и говорит сообщение об ошибке в ПП.

Note: тем не менее, я не понимаю почему корректно работают конструкции с пайпом и eval-ом =)

Но суть проблемы я понял. Решение — испоьзовать массив вместо строки. Потому что bash может смотреть на исполняемое значение в строке так и только так:

  • "$a" — это одна команда, вне зависимости от предполагаемого количества аргументов, экранируемых символов, и т. д. ls /dev (например) — одна команда; ls — не команда, а /dev — не аргумент, но ls /dev — одна команда.
  • $a — bash всё-таки попытается отделить команду от аргументов и правильно их выполнить, но может ошибиться из-за пробелов:
    • a='ls arch' && $a == ls arch (здесь всё нормально);
    • a='ls "arch linux"' == ls \"arch linux\" (т. е. ls для директорий "arch и linux", но не для "arch linux");

Хинт: суть в том, что мы не можем достаточно (достаточно для корректности) точно задать команду в строке; во втором примере мы не можем указать начало и конец первого аргумента, bash это делает за нас.

Исправление kalterfive, :

Твой код фиксится до рабочего так:

$ a="watch \"\$(df -h |grep ^[/F];free -h|sed 's/  \*/ /g')|sed 8q\""
$ $a

Это конструкция $( ... ) (man 1 bash | grep 'Command Substitution'). Если использовать её, то на место первого аргумента bash подставит результат выполнения некоторой команды в этой конструкции. Если же её не использовать, то watch получит первым аргументом саму команду, а не результат её выполнения — об этом и говорит сообщение об ошибке в ПП.

Note: тем не менее, я не понимаю почему корректно работают конструкции с пайпом и eval-ом =)

Но суть проблемы я понял. Решение — испоьзовать массив вместо строки. Потому что bash может смотреть на исполняемое значение в строке так и только так:

  • "$a" — это одна команда, вне зависимости от предполагаемого количества аргументов, экранируемых символов, и т. д. ls /dev (например) — одна команда; ls — не команда, а /dev — не аргумент, но ls /dev — одна команда.
  • $a — bash всё-таки попытается отделить команду от аргументов и правильно их выполнить, но может ошибиться из-за пробелов:
    • a='ls arch' && $a == ls arch (здесь всё нормально);
    • a='ls "arch linux"' == ls \"arch linux\" (т. е. ls для директорий "arch и linux", но не для "arch linux");
    • Хинт: суть в том, что мы не можем достаточно (достаточно для корректности) точно задать команду в строке; во втором примере мы не можем указать начало и конец первого аргумента, bash это делает за нас.

Исправление kalterfive, :

Твой код фиксится до рабочего так:

$ a="watch \"\$(df -h |grep ^[/F];free -h|sed 's/  \*/ /g')|sed 8q\""
$ $a

Это конструкция $( ... ) (man 1 bash | grep 'Command Substitution'). Если использовать её, то на место первого аргумента bash подставит результат выполнения некоторой команды в этой конструкции. Если же её не использовать, то watch получит первым аргументом саму команду, а не результат её выполнения — об этом и говорит сообщение об ошибке в ПП.

Note: тем не менее, я не понимаю почему корректно работают конструкции с пайпом и eval-ом =)

Но суть проблемы я понял. Решение — испоьзовать массив вместо строки. Потому что bash может смотреть на исполняемое значение в строке так и только так:

  • "$a" — это одна команда, вне зависимости от предполагаемого количества аргументов, экранируемых символов, и т. д. ls /dev (например) — одна команда; ls — не команда, а /dev — не аргумент, но ls /dev — одна команда.
  • $a — bash всё-таки попытается отделить команду от аргументов и правильно их выполнить, но может ошибиться из-за пробелов:
    • a='ls arch' && $a == ls arch;
    • a='ls "arch linux"' == ls \"arch linux\" (т. е. ls для директорий "arch и linux", но не для "arch linux");
    • Хинт: суть в том, что мы не можем достаточно (достаточно для корректности) точно задать команду в строке; во втором примере мы не можем указать начало и конец первого аргумента, bash это делает за нас.

Исходная версия kalterfive, :

Твой код фиксится до рабочего так:

$ a="watch \"\$(df -h |grep ^[/F];free -h|sed 's/  \*/ /g')|sed 8q\""
$ $a

Это конструкция $( ... ) (man 1 bash | grep 'Command Substitution'). Если использовать её, то на место первого аргумента bash подставит результат выполнения некоторой команды в этой конструкции. Если же её не использовать, то watch получит первым аргументом саму команду, а не результат её выполнения.

Note: тем не менее, я не понимаю почему корректно работают конструкции с пайпом и eval-ом =)

Но суть проблемы я понял. Решение — испоьзовать массив вместо строки. Потому что bash может смотреть на исполняемое значение в строке так и только так:

  • "$a" — это одна команда, вне зависимости от предполагаемого количества аргументов, экранируемых символов, и т. д. ls /dev (например) — одна команда; ls — не команда, а /dev — не аргумент, но ls /dev — одна команда.
  • $a — bash всё-таки попытается отделить команду от аргументов и правильно их выполнить, но может ошибиться из-за пробелов:
    • a='ls arch' && $a == ls arch;
    • a='ls "arch linux"' == ls \"arch linux\" (т. е. ls для директорий "arch и linux", но не для "arch linux");
    • Хинт: суть в том, что мы не можем достаточно (достаточно для корректности) точно задать команду в строке; во втором примере мы не можем указать начало и конец первого аргумента, bash это делает за нас.