Исправление
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"
);
Исправление
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"
);
Исходная версия
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"
);