Я плохо знаком с UNIX, только запустив его на работе сегодня, но опытный с Java, и имею следующий код:
#/bin/bash
echo "Please enter a word:"
read word
grep -i $word $1 | cut -d',' -f1,2 | tr "," "-"> output
Это хорошо работает, но что я теперь должен сделать, должен проверить, когда слово читается, что оно содержит только буквы и если оно имеет цифровые символы в печати "Недопустимый вход!" передайте и попросите, чтобы они ввели его снова. Я принял регулярные выражения с, если оператор будет простым способом сделать это, но я не могу получить голову вокруг, как использовать их в UNIX, как я привык к JAVA-приложению их. Любая справка с этим значительно ценилась бы, поскольку я не мог найти справку при поиске как все решения с регулярными выражениями в Linux, который я нашел, только имел дело с тем, если это были или все числовые или нет.
Еще один подход. Grep завершает работу с 0
, если найдено совпадение, поэтому вы можете проверить код выхода:
echo "${word}" | grep -q '[0-9]'
if [ $? = 0 ]; then
echo 'Invalid input'
fi
Это / bin / sh
совместимо.
Включая предложения Дейнит и Джона, получается
if echo "${word}" | grep '[0-9]' >/dev/null; then
echo 'Invalid input'
fi
Если вы пытаетесь написать переносимый код оболочки, ваши возможности для обработки строк ограничены. Вы можете использовать шаблоны подстановки оболочки (которые намного менее выразительны, чем регулярные выражения) в конструкции case
:
export LC_COLLATE=C
read word
while
case "$word" in
*[!A-Za-z]*) echo >&2 "Invalid input, please enter letters only"; true;;
*) false;;
esac
do
read word
done
EDIT : установка LC_COLLATE
необходима, потому что в большинстве не- Локали C
, диапазоны символов вроде AZ
не имеют «очевидного» значения. Я предполагаю, что вам нужны только буквы ASCII; если вам также нужны буквы с диакритическими знаками, не меняйте LC_COLLATE
, а замените A-Za-z
на [: alpha:]
(чтобы весь шаблон становится * [! [: alpha:]] *
).
Полные регулярные выражения см. В команде expr
. РЕДАКТИРОВАТЬ : Обратите внимание, что expr
, как и некоторые другие базовые инструменты оболочки, имеет подводные камни с некоторыми специальными строками; символы z
ниже не позволяют $ word
интерпретировать как зарезервированные слова expr
.
export LC_COLLATE=C
read word
while expr "z$word" : 'z[A-Za-z]*$' >/dev/null; then
echo >&2 "Invalid input, please enter letters only"
read word
fi
Если вы ориентируетесь только на достаточно свежие версии bash, есть другие варианты, такие как оператор = ~
условных команд [[...]]
.
Обратите внимание, что ваша последняя строка содержит ошибку, первая команда должна быть
grep -i "$word" "$1"
Кавычки сделаны потому, что несколько нелогично «$ foo»
означает «значение переменной с именем foo
», тогда как plain $ foo
означает« взять значение foo
, разделить его на отдельные слова, содержащие пробелы, и обработать каждое слово как шаблон подстановки и попытаться расширить его ». (На самом деле, если вы уже проверили, что $ word
содержит только буквы, оставление кавычек не повредит, но нужно больше времени, чтобы подумать об этих особых случаях, чем просто помещать кавычки каждые раз.)
Один переносимый (при условии, что bash> = 3) способ сделать это - удалить все числа и проверить длину:
#!/bin/bash
read -p "Enter a number" var
if [[ -n ${var//[0-9]} ]]; then
echo "Contains non-numbers!"
else
echo "ok!"
fi
Исходя из Java, важно отметить, что bash не имеет реальной концепции объектов или типов данных. Все является строкой, а сложные структуры данных в лучшем случае болезненны.
Для получения дополнительной информации о том, что я сделал, и других связанных функциях, используйте google для обработки строк в bash.
Оператор двойной скобки - это расширенная версия команды test
, которая поддерживает регексы через оператор =~
:
#!/bin/bash
while true; do
read -p "Please enter a word: " word
if [[ $word =~ [0-9] ]]; then
echo 'Invalid input!' >&2
else
break
fi
done
Это специфическая для Bash функция. Bash - это более новая оболочка, которая доступна не на всех версиях UNIX - хотя под "более новой" я подразумеваю "только недавно разработанную в эпоху после вакуумной трубки", а под "не на всех версиях UNIX" я подразумеваю реликты вроде старых версий Solaris и HP-UX.
На мой взгляд, это самый простой вариант, и bash достаточно переносим в наши дни, но если переносимость на старые UNIX'ы действительно важна, то вам нужно использовать sh-совместимые ответы других плакатов. sh - самая распространенная и наиболее широко поддерживаемая оболочка, но цена, которую вы платите за переносимость - это потеря таких вещей, как =~
.
Еще один (вполне) переносимый способ сделать это ...
if test "$word" != "`printf "%s" "$word" | tr -dc '[[:alpha:]]'`"; then
echo invalid
fi
Игра с расширением параметров Bash и классами символов:
# cf. http://wiki.bash-hackers.org/syntax/pe
word="abc1def"
word="abc,def"
word=$'abc\177def'
# cf. http://mywiki.wooledge.org/BashFAQ/058 (no NUL byte in Bash variable)
word=$'abc\000def'
word="abcdef"
(
set -xv
[[ "${word}" != "${word/[[:digit:]]/}" ]] && echo invalid || echo valid
[[ -n "${word//[[:alpha:]]/}" ]] && echo invalid || echo valid
)