В Bash как проверить, начинается ли строка с определённого значения?
Я хотел бы проверить, начинается ли строка с "node", например, "node001". Что-то вроде:
if [ $HOST == node* ]
then
echo yes
fi
Как я могу сделать это правильно?
Кроме того, мне нужно объединить выражения, чтобы проверить, является ли переменная HOST
либо "user1", либо начинается с "node":
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
> > > -bash: [: слишком много аргументов
Как я могу сделать это правильно?
5 ответ(ов)
Я всегда стараюсь придерживаться POSIX sh
вместо использования расширений Bash, так как одной из основных целей сценарного программирования является портативность (кроме связывания программ, а не замены их).
В sh
есть простой способ проверить условие "является префиксом".
case $HOST in node*)
# Ваш код здесь
esac
С учетом того, насколько старым, архаичным и неуклюжим является sh
(и Bash не является решением: он более сложен, менее последователен и менее портативен), я хотел бы указать на очень приятный функциональный аспект: хотя некоторые элементы синтаксиса, такие как case
, являются встроенными, полученные конструкции не отличаются от любых других заданий. Их можно комбинировать так же:
if case $HOST in node*) true;; *) false;; esac; then
# Ваш код здесь
fi
Или даже короче:
if case $HOST in node*) ;; *) false;; esac; then
# Ваш код здесь
fi
Или даже короче (просто чтобы продемонстрировать !
как элемент языка — но это плохой стиль):
if ! case $HOST in node*) false;; esac; then
# Ваш код здесь
fi
Если вам нравится быть явным, создайте свой собственный элемент языка:
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
Разве это не очень приятно?
if beginswith node "$HOST"; then
# Ваш код здесь
fi
Поскольку sh
в основном представляет собой только задания и списки строк (и внутренние процессы, из которых состоят задания), мы можем даже заниматься легким функциональным программированием:
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
checkresult() { if [ $? = 0 ]; then echo TRUE; else echo FALSE; fi; }
all() {
test=$1; shift
for i in "$@"; do
$test "$i" || return
done
}
all "beginswith x" x xy xyz ; checkresult # Выводит TRUE
all "beginswith x" x xy abc ; checkresult # Выводит FALSE
Это элегантно. Не то чтобы я рекомендовал использовать sh
для чего-то серьезного — он слишком быстро ломается при реальных требованиях (нет лямбд, поэтому мы вынуждены использовать строки. Но вложенные вызовы функций со строками невозможны, пайпы невозможны и т.д.)
Я предпочитаю другие методы, уже приведенные в обсуждении, но некоторые люди любят использовать:
case "$HOST" in
user1|node*)
echo "yes";;
*)
echo "no";;
esac
Правка:
Я добавил ваши альтернативы в оператор case
выше.
В вашей отредактированной версии у вас слишком много скобок. Правильный вариант должен выглядеть так:
if [[ $HOST == user1 || $HOST == node* ]]; then
echo "yes"
else
echo "no"
fi
В Bash символ #
используется для обозначения комментариев, что создает некоторые сложности при работе с такими строками. Однако я нашёл следующее решение:
Мне также больше нравится заключать строки в кавычки, чтобы избежать проблем с пробелами и другими символами.
Вот пример кода:
A="#sdfs"
if [[ "$A" == "#"* ]]; then
echo "Пропустить строку комментария"
fi
Таким образом, если переменная A
начинается с символа #
, программа выведет "Пропустить строку комментария".
Добавляя немного больше синтаксиса к ответу Марка Рушакоффа с наивысшим рейтингом.
Выражение
$HOST == node*
можно также записать как
$HOST == "node"*
Эффект остается тем же. Просто убедитесь, что подстановочный знак находится вне кавычек. Если же подстановочный знак окажется внутри кавычек, он будет интерпретироваться буквально (т.е. не как подстановочный знак).
Ваш код на Bash проверяет, начинается ли строка word
с буквы "a". Вот перевод с объяснением:
word="appel"
if [[ $word = a* ]]
then
echo "Начинается с a"
else
echo "Нет совпадения"
fi
Здесь [[ $word = a* ]]
— это условие, которое использует шаблон для проверки, начинается ли переменная word
с буквы "a". Если условие истинно, выводится сообщение "Начинается с a", иначе — "Нет совпадения".
Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать!
Как проверить, содержит ли строка подстроку в Bash
Извлечение имени файла и расширения в Bash
Почему сравнение строк с помощью '==' и 'is' иногда дает разные результаты?
Извлечение подстроки в Bash
Как проверить, содержит ли строка подстроку?