Таким образом, это работает бесконечно в Bash/dash/ksh/zsh (или, по крайней мере, до тех пор, пока ваш диск не заполнится):
#!/bin/sh
s=$0
foo() { echo "hello"; echo "foo" >> $s; sleep.1; }
foo
Следует отметить, что имеет значение только то, что добавлено в файл сценария после последней строки, прочитанной оболочкой. Оболочки не возвращаются назад, чтобы -прочитать более ранние части, чего они даже не могли бы сделать, если бы ввод был каналом.
Подобная конструкция не работает в Perl, она считывает весь файл перед запуском.
#!/usr/bin/perl -l
open $fd, ">>", $0;
sub foo { print "hello"; print $fd 'foo;' }
foo;
Мы можем видеть, что это происходит и при вводе данных через канал. Это дает синтаксическую ошибку (и только это )через 1 секунду:
$ (echo 'printf "hello\n";' ; sleep 1 ; echo 'if' ) | perl
В то время как тот же скрипт передается, например,. Bash печатает hello
, а через секунду выдает синтаксическую ошибку.
Python похож на Perl с конвейерным вводом, даже несмотря на то, что интерпретатор запускает цикл чтения -eval -печати в интерактивном режиме.
В дополнение к чтению входной строки скрипта -по -строке, как минимум Bash и dash обрабатывают аргументы для eval
по одной строке за раз:
$ cat evaltest.sh
var='echo hello
fi'
eval "$var"
$ bash evaltest.sh
hello
evaltest.sh: eval: line 4: syntax error near unexpected token `fi'
evaltest.sh: eval: line 4: `fi'
Zsh и ksh немедленно выдают ошибку.
Аналогично для исходных скриптов, на этот раз Zsh также запускает строку -за строкой -, так же как Bash и тире:
$ cat sourceme.sh
echo hello
fi
$ zsh -c '../sourceme.sh'
hello
./sourceme.sh:2: parse error near `fi'
Решение благодаря @ctrl -alt -delor было следующим:
test $(realm list | grep active-directory | wc -l) -lt 2 && echo true || echo false
test
— стандартная утилита POSIX
if [ "$(realm list | grep -c -wF active-directory)" -lt 2 ]; then
echo is less than 2
else
echo is 2 or more
fi
grep
умеет считать. Здесь мы используем этот факт для подсчета количества строк, содержащих слово active-directory
.
Параметр -c
для grep
заставляет grep
возвращать количество совпадающих строк. Опция -F
отключает сопоставление регулярных выражений и заставляет grep
вместо этого использовать сравнение строк.
Опция -w
не является стандартной -, но обычно используется. Это заставляет заданный шаблон быть отдельным словом, а это означает, что совпадение должно иметь не -словесные символы (или ничего )с обеих сторон данной строки. Не -словесный символ — это любой символ вне набора [[:alnum:]_]
, т. е. все, что не является буквенно-цифровым символом или символом подчеркивания. Это означает, что active-directory3
не будет соответствовать active-directory
, если -w
используется с grep
, и inactive-directory
тоже не будет.
Вы также можете
if realm list | awk '/active-directory/ && n++ {exit 1}'; then
echo less than 2
else
echo 2 or more
fi
Мы говорим awk
выйти с "ложным" статусом выхода, как только он найдет вторую строку, содержащую active-directory
. Это избавляет от необходимости искать все совпадения, когда у нас уже есть ответ к секунде.