Назад | Перейти на главную страницу

Как найти соответствие текста в bash

Я пытаюсь найти хороший способ проверить текст, чтобы установить переменную. Например, для выполнения логики: «если строка версии 1.x, установите флаг». Один из способов сделать это:

versionFlag="0"
if grep -q "^1.*" versionfile; then
  versionFlag="1"
fi

что немного многословно. Если я хочу включить несколько возможностей, это проще:

case `grep "^1.*" versionfile` in
  1.*)
    echo "version 1"
    ;;
...
esac

Но есть ли хороший однострочный способ просто установить флаг как истинный или ложный, если некоторый текст соответствует регулярному выражению или подстановочному знаку?

versionFlag=`grep "^1.*" /tmp/test | wc -l`

versionFlag затем устанавливается в 0. Любые данные в тестовых совпадениях, versionFlag устанавливается на количество совпадающих строк, поэтому

if [ $versionFlag == 0 ] ; then
  echo false
else
  echo true 
fi

изменить: это можно сделать еще проще

versionFlag=$(grep "^1.*" /tmp/test -c)

который вернет количество экземпляров в файле

Вы можете сделать что-то подобное в bash 3.x (более старые версии не поддерживают сопоставление регулярных выражений)

version=`cat versionfile`
[[ $version =~ "^1.*" ]] && versionFlag=1

В bash нет тернарного оператора (например,? :), так что вы застряли со своим if, then строите на нескольких строках. Вы можете использовать другой язык, в котором есть тернарный оператор (например, PERL).

Имейте в виду, что многие люди не одобряют использование тернарных операторов, поскольку их не так просто читать в коде - другими словами, ваши комментарии в конечном итоге длиннее, чем были бы несколько строк кода.

Я сомневаюсь, что у обоих методов есть преимущество в производительности.

Собственно эта конструкция:

[[ $version =~ ^1\.+ ]] && versionFlag=1

легко расширяется для поддержки случая «несоответствия»; просто сделай это:

[[ $version =~ ^1\.+ ]] && versionFlag=1 || versionFlag=0

Кстати, обратите внимание на изменение регулярного выражения с «*» на «+». При использовании звездочки регулярное выражение по-прежнему будет неправильно соответствовать значению версии "10". (Модификатор '*' означает «совпадение нуля или нескольких вхождений», т. Е. Вам по-прежнему не требуется десятичная точка; модификатор «+» означает «совпадение одного или нескольких вхождений».) Однако внесение этого изменения будет , означает, что "1" (т. е. значение без десятичной дроби) будет не соответствие; это может быть или не быть проблемой для вашего приложения.

Есть также способ сделать это без использования оператора регулярного выражения, если он у вас отсутствует; попробуй это:

[[ ${version#1.} != ${version} ]] && versionFlag=1 || versionFlag=0

Это просто сопоставление с шаблоном, а не регулярное выражение, поэтому, если вам действительно нужна функциональность регулярного выражения, это не сработает, но для простых вещей это здорово. (Если вы не знакомы с этой формой расширения параметров, конструкция «$ {version # 1.}» Расширяется до значения «version», но с удалением шаблона post - '#' из начала значения если он изначально был там. Пример: Если "версия" имеет значение "1.03", результатом "$ {version # 1.}" будет "03". Поскольку это значение отличается от исходного значения, "! =" тест успешен.)