Я пытался сделать это, чтобы решить, перенаправить ли stdin в файл или нет:
[ ...some condition here... ] && input=$fileName || input="&0"
./myScript < $input
Но это не работает, потому что, когда переменный $input является "&0", удар интерпретирует его как имя файла.
Однако я мог просто сделать:
if [ ...condition... ];then
./myScript <$fileName
else
./myScript
Проблема состоит в том, что./myScript является на самом деле долгой командной строкой, которую я не хочу копировать, и при этом я не хочу создавать функцию для него, потому что дело не в этом долго любой (это не стоит того).
Тогда мне пришло в голову делать это:
[ ...condition... ] && input=$fileName || input= #empty
cat $input | ./myScript
Но это требует для выполнения еще одной команды и канала (т.е. подоболочка).
Есть ли иначе, это более просто и более эффективно?
В первую очередь stdin - это файловый дескриптор 0 (ноль), а не 1 (то есть stdout).
Можно дублировать файловые дескрипторы или использовать имена файлов условно, как это делается:
[[ some_condition ]] && exec 3<"$filename" || exec 3<&0
some_long_command_line <&3
Обратите внимание, что показанная команда выполнит второе exec
, если либо условие ложно , либо , если первое exec
не срабатывает. Если вы не хотите, чтобы это не сработало, то вы должны использовать if
/ else
:
if [[ some_condition ]]
then
exec 3<"$filename"
else
exec 3<&0
fi
, но последующие перенаправления из файлового дескриптора 3 будут неудачными, если первое перенаправление не сработало (после того, как условие было истинным).
. Стандартный вход также может быть представлен файлом специального устройства /dev/stdin
, так что использование в качестве имени файла будет работать.
file="/dev/stdin"
./myscript < "$file"
(
if [ ...some condition here... ]; then
exec <$fileName
fi
exec ./myscript
)
В подобложке, условно перенаправить stdin и выполнить скрипт.
Как насчет
function runfrom {
local input="$1"
shift
case "$input" in
-) "$@" ;;
*) "$@" < "$input" ;;
esac
}
Я использовал знак минус для обозначения стандартного ввода, потому что это традиционно для многих программ Unix.
Теперь вы пишите
[ ... condition ... ] && input="$fileName" || input="-"
runfrom "$input" my-complicated-command with many arguments
Я нахожу эти функции/команды, которые принимают команды в качестве аргументов (например, xargs(1)
) очень полезными, и они хорошо сочиняются.
Это действительно очень неясное объяснение, и алгоритм, похоже, не исходит ни из одной из перечисленных ссылок.
Идея, кажется, чтобы сначала сделать случайный путь, выбирая начальный узел наугад и происхождение этого, выбирая случайных соседей столько, сколько это возможно. Когда больше соседей не может быть выбрано, или путь гамильтонов, или это не. Если это не, у этого последнего узла на пути есть некоторый сосед уже на пути (см. ниже), таким образом, поворотное средство делает край от последнего узла к соседу, уже находящемуся на пути, и удаляет одну из линий связи из соседа, которые были выбраны для пути. Затем происходит новый конец пути, с которого процесс продолжается.
Этот алгоритм предполагает, например, что отсутствуют узлы только с одним краем. Эти легко прикрыть, хотя: если есть один из них, просто начните с того, если их два, начните с одного из них и попытайтесь в итоге оказаться на другом, а если их больше двух, гамильтонова тропа быть не может.
-121--3665417- c++ 0x будет иметь decltype
, который можно использовать так:
int someInt;
decltype(someInt) otherIntegerVariable = 5;
, но для простых старых c++, к сожалению, нет.
Я полагаю, что decltype
не очень поможет, хотя, поскольку вы хотите полиморфный тип, не объявленный тип. Самый прямой способ сделать то, что вы хотите, это попытаться динамически привести к определенному типу и проверить NULL
.
struct A {
virtual ~A() {}
};
struct B : public A {};
struct C : public A {};
int main() {
A* x = new C;
if(B* b_ptr = dynamic_cast<B*>(x)) {
// it's a B
} else if(C* c_ptr = dynamic_cast<C*>(x)) {
// it's a C
}
}
-121--4780477- Если вы осторожны, вы можете использовать « eval
» и свою первую идею.
[ ...some condition here... ] && input=$fileName || input="&1"
eval ./myScript < $input
Однако вы говорите, что «myScript» на самом деле является сложным вызовом команды; если он содержит аргументы, которые могут содержать места, необходимо быть очень осторожными, прежде чем принимать решение об использовании « eval
».
Честно говоря, беспокойство по поводу стоимости команды ' cat
', вероятно, не стоит неприятностей; вряд ли это будет узким местом.
Еще лучше разработать myScript
так, чтобы он работал как обычный Unix-фильтр - он считывает со стандартного ввода, если ему не дается один или несколько файлов для работы (например, cat
или grep
в качестве примеров). Эта конструкция основана на долгом и здравом опыте - и поэтому стоит подражать, чтобы избежать необходимости иметь дело с такими проблемами, как эта.
Документы требуются 4 различных механизма хранения. Двигатель TapbackStorage
пишет на сеанс.
Использование EVAL
:
#! /bin/bash
[ $# -gt 0 ] && input="'"$1"'" || input="&1"
eval "./myScript <$input"
Эта простая подставка для MyScript
#! /usr/bin/perl -lp
$_ = reverse
производит следующий вывод:
$ ./myDemux myScript pl- lrep/nib/rsu/ !# esrever = _$ $ ./myDemux foo oof bar rab baz zab
Обратите внимание, что он обрабатывает пробелы в входах Слишком:
$ ./myDemux foo\ bar eman eht ni ecaps a htiw elif
для ввода трубы до MyScript
, используйте , используйте подстановку процесса :
$ ./myDemux <(md5sum /etc/issue) eussi/cte/ 01672098e5a1807213d5ba16e00a7ad0
Обратите внимание, что если вы попытаетесь трусить вывод напрямую, как в
$ md5sum /etc/issue | ./myDemux
Ожидание на входе от терминала, тогда как Ответ эфемиента не имеет этого недостатка.
Небольшое изменение производит желаемое поведение:
#! /bin/bash
[ $# -gt 0 ] && input="'"$1"'" || input=/dev/stdin
eval "./myScript <$input"