В оболочке Bourne есть конструкция для этого. Это то же самое, что и в современном sh
(который больше похож на то, что вы используете, оболочка Bourne не поддерживает $ (...)
; если это была оболочка Bourne , вы получите другую ошибку):
case $1 in
*"$2"*) printf '"%s" is in "%s"\n' "$2" "$1"
esac
Если вы хотите использовать grep
, это будет:
if printf '%s\n' "$1" | grep -Fqe "$2"; then
printf '"%s" is in "%s"\n' "$2" "$1"
fi
или
if grep -Fqe "$2" << EOF
$1
EOF
then
printf '"%s" is in "%s"\n' "$2" "$1"
fi
Но это будет работать правильно, только если $ 2
не содержал символа новой строки.
В любом случае, вам нужно заключить в кавычки большую часть этого расширения параметров. Единственное место, где он не нужен, - это случай $ 1
выше, но даже тогда случай «1 доллар»
не повредит.
Несколько примечаний к вашему коду:
echo
для произвольных строк .Здесь, в зависимости от реализации echo
, он не сработает для значений $ 1
, например -n
или foo \ bar
. grep -c $ 2
со значением $ 2
, например *
или root / etc / passwd
. grep
без -F
предназначен для сопоставления регулярных выражений. Вам понадобится -F
для поиска по фиксированной строке (подстроке) (раньше было с fgrep
), но опять же, если $ 2
содержит несколько строк, это говорит grep -F
для поиска любого содержимого этих строк во входных данных ( grep -F $ 'a \ nb'
будет искать a
] или b
, а не $ 'a \ nb'
строка). grep -c $ 2
содержимое $ 2
будет использоваться в качестве опции, если оно начинается с -
. Чтобы этого избежать, вы хотите grep -c -e "$ 2"
или grep -c - "$ 2"
. exit
( exit 0
для истины, exit 1
(или любое ненулевое число, но избегайте значений больше 120) для false). Для функций используйте вместо этого return
. Хотя и скрипты, и функции вернутся со статусом последней команды запуска. $ (cmd)
расширяет до вывода cmd
(и подвергается здесь split + glob из-за отсутствия кавычек снова) за вычетом завершающих символов новой строки. Таким образом, если cmd
выводит 0 \ n
, $ (cmd)
расширяется до 0
. Итак, при запуске $ (cmd)
пытается выполнить команду с именем 0
. Если вы хотите преобразовать вывод cmd
в статус выхода (чтобы его можно было использовать как логическое), вам понадобится (exit «$ (cmd)»)
. Это запускает подоболочку, которая завершается с выводом cmd
в качестве кода выхода). grep -c
подсчитывает количество вхождений. Здесь вам не обязательно иметь полный счет, вам нужно только знать, найдено ли оно вообще (есть ли хотя бы одно совпадение).Для этого grep -q
более эффективен, так как он прекращает поиск после того, как нашел его. Для старых реализаций grep
, которые не поддерживают (стандартный) -q
параметр, вы можете использовать fgrep -le "$ 2"> / dev / null
. С -l
, fgrep
также останавливается при первом совпадении, но выводит имя файла (которое мы здесь отбрасываем, перенаправляя вывод на / dev / null
) . Вы можете приостановить только awk
и промыть канал, который он читает, из-под ног, прежде чем возобновить его. В системах на базе Linux и с GNU dd
:
Где $ pid
- это PID awk
:
kill -s STOP "$pid"
, чтобы остановить его, и
dd iflag=nonblock if="/proc/$pid/fd/0" > /dev/null; kill -s CONT "$pid"
возобновить.
Предполагается, что канал не заполнен (64 КБ по умолчанию в Linux), иначе tail
также мог быть заблокирован. Чтобы обойти это, вы можете промыть трубу с помощью:
socat -T0.2 -u "/proc/$pid/fd/0" /dev/null
Это промоет то, что в данный момент находится в трубе, и продолжит чтение до тех пор, пока не перестанет поступать в течение 0,2 секунды, чтобы позволить tail
догнать то, что он не имеет » Не читал из файла, если он есть.