bash-скрипт для проверки наличия @ во входных данных

bash-скрипт для проверки наличия @ во входных данных

Привет, я пытаюсь написать скрипт bash, в котором входные данные проверяются на наличие символа @. Я относительно новичок в bash, поэтому, пожалуйста, простите за любые ошибки! Пока что у меня есть:

var1="@"
var2="INPUT"

echo "input"
read INPUT

if [[ "$var2" == "$var1" ]]; then
echo "pass"
else
echo "fail"
fi

решение1

Хотя у вас есть возможность использовать встроенную функциональность оболочки для проверки того, содержит ли ввод пользователя что-либо @(что хорошо документировано в других ответах), другой разумный способ сделать это — использовать внешнюю оболочкуgrepполезность:

#!/usr/bin/env bash

read -erp '> '
if grep -q @ <<<"$REPLY"; then
    echo pass
else
    echo fail
fi

Передача -qфлага grepзапрещает ему печатать совпадающие строки. (Это также не позволяет ему считывать дополнительные строки после нахождения совпадения, но в данном случае это не имеет значения, поскольку имеется только одна строка ввода.)

Возникает соблазн сократить ifконструкцию до чего-то вроде grep -q @ <<<"$REPLY" && echo pass || echo fail, но я намеренно избегаю этого:

  • В этом случае, это, вероятно, нормально, поскольку единственный способ, которым неправильное слово печатается, это если оно passдолжно было быть напечатано, но echoне печаталось. Тогда, предположительно, echo failтакже не печатается.
  • Хотя короткое замыкание &&и ||часто сами по себе уместны (и я часто использую их для сокращенияif безпредложение else), используя их вместе, как будто онитроичныйеслиоператорна самом деле не очень хорошая привычка. Хотя некоторые команды не могутнеудача,echo может.
  • Если пользовательперенаправляетвывод вашего скрипта в неперезаписываемый файл или устройство или использование его в неисправномтрубопровод, echo и другие команды, выводящие текст, могут возвращать ошибку, что приводит к сбою выражения и выполнению &&правой части выражения .||
  • Вы можете проверить поведение скрипта при наличии недоступного для записи устройства вывода, запустив его с помощью >/dev/full.

Этот скрипт использует несколько функций bash:

  • -eвключает GNU Readline, так что пользователь может перемещать курсор влево и вправо с помощью клавиш со стрелками, чтобы редактировать вводимые данные во время их ввода.
  • В bash readавтоматически помещает введенные пользователем данные в REPLYпеременную, если переменная не указана.
  • Аздесь строкаwith <<<— это удобный способ передать введенные пользователем данные в grep.
  • Баш инекоторыйдругие оболочки в стиле Bourne, такие как dash accept -p. НоОболочки, совместимые с POSIX, должны понимать только-r. А в некоторых, как ksh, -pимеет другое значение.
    (Спасибогейраза указание того, что-pиногда отсутствуети чтоэто не всегда означает «быстро».)

Если вам нужен скрипт, который можно переносить на другие ОС, в которых может быть не установлен bash, вы можете использовать:

#!/bin/sh

printf '> '
read -r line

if printf '%s' "$line" | grep -q @; then
    echo pass
else
    echo fail
fi

Если хотите, вы можете пропустить сохранение введенных пользователем данных в переменной, прочитав их с помощьюheadвместо read:

#!/bin/sh

printf '> '
if head -1 | grep -q @; then
    echo pass
else
    echo fail
fi

Какгейра упомянула, head -n 1можно считать лучшим синтаксисом, как head -1естьофициально устарел(хотя текущие sedреализации, или, по крайней мере, GNU sed, поддерживают -1в своих последних версиях, в то время как некоторые очень старые sedреализации не поддерживают -n 1).

Какдокументацияheadговорит, вы можете использовать sedвместо этого для максимальной портативности.

#!/bin/sh

printf '> '
if sed 1q | grep -q @; then
    echo pass
else
    echo fail
fi

решение2

Этот bashкод считывает входные данные и выдает сигнал «Пройдено», если входные данные содержат @символ:

read -p "Input: " var
[ "${var//[^@]/}" ] && echo Pass || echo Fail

Примечания:

  • [ "$var" ]это тест bash. Он возвращает true, если строка $varнепустая.

  • Одной из функций bash является подстановка шаблона. Выглядит как ${var//pattern/string}. Он заменяет каждое вхождение patternin varна string. В нашем случае patternэто , [^@]которое является регулярным выражением, которое соответствует каждому символукроме @. Таким образом, ${var//[^@]/}возвращается пустая строка, если она varне содержит хотя бы одного @.

  • Мы объединяем два вышеперечисленных пункта:

    [ "${var//[^@]/}" ]
    

    Этот тест успешен только в том случае, если ${var//[^@]/}непустой, и ${var//[^@]/}непустой только в том случае, если varсодержит хотя бы один @.

Использование явного if-then-else:

read -p "Input: " var
if [ "${var//[^@]/}" ]
then
    echo Pass
else
    echo Fail
fi

Оболочка POSIX

Следующее работает в dash( /bin/sh) и должно работать в любой оболочке POSIX:

printf "Input: "
read var
case "$var" in
    *@*) echo Pass
        ;;
    *) echo Fail
        ;;
esac

Оболочка POSIX не поддерживает -pопциюread. Таким образом, вместо этого используется комбинация printfи . Кроме того, из-за отсутствия расширенных возможностей расширения переменных , оператор может использоваться для сопоставления glob.readbashcase

Оболочка Android

Используя оболочку по умолчанию на моем Android, работает следующее:

echo -n "Input: "; read var
if ! [ "${var//@/}" = "$var" ]
then
    echo Pass
else
    echo Fail

решение3

Предпочтительным способом в bash является использование функции сопоставления с образцом [[ ... ]].

#bash
read -rp "Input: " input
if [[ $input = *@* ]]; then
    printf '<%s> contains @\n' "$input"
fi

Для shскриптов вы можете использовать caseвместо этого.

#sh
printf 'Input: '
read -r input
case $input in
    *@*) printf '<%s> contains @\n' "$input" ;;
esac

Смотрите такжеТесты и условные предложенияглава руководства Bash.

решение4

В новых версиях bash вы сможете использоватьрегулярное выражение совпадениечерез =~расширенный тестовый оператор:

$ read -p "input: " input
input: quertyuiop 
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
no match
$ 
$ read -p "input: " input
input: qwerty@uiop
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
match

Альтернативой, которая должна работать в любой совместимой с POSIX системе, является использование, exprнапример, в dashоболочке:

$ read input
qwertyuiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
no match
$ 
$ read input
qwerty@uiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
match
$ 

Связанный контент