Проверка строки, чтобы видеть, содержит ли это цифровой символ в UNIX

Я плохо знаком с UNIX, только запустив его на работе сегодня, но опытный с Java, и имею следующий код:

#/bin/bash
echo "Please enter a word:"
read word
grep -i $word $1 | cut -d',' -f1,2 | tr "," "-"> output

Это хорошо работает, но что я теперь должен сделать, должен проверить, когда слово читается, что оно содержит только буквы и если оно имеет цифровые символы в печати "Недопустимый вход!" передайте и попросите, чтобы они ввели его снова. Я принял регулярные выражения с, если оператор будет простым способом сделать это, но я не могу получить голову вокруг, как использовать их в UNIX, как я привык к JAVA-приложению их. Любая справка с этим значительно ценилась бы, поскольку я не мог найти справку при поиске как все решения с регулярными выражениями в Linux, который я нашел, только имел дело с тем, если это были или все числовые или нет.

7
задан indiv 19 July 2010 в 20:30
поделиться

6 ответов

Еще один подход. 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
17
ответ дан 6 December 2019 в 06:02
поделиться

Если вы пытаетесь написать переносимый код оболочки, ваши возможности для обработки строк ограничены. Вы можете использовать шаблоны подстановки оболочки (которые намного менее выразительны, чем регулярные выражения) в конструкции 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 содержит только буквы, оставление кавычек не повредит, но нужно больше времени, чтобы подумать об этих особых случаях, чем просто помещать кавычки каждые раз.)

3
ответ дан 6 December 2019 в 06:02
поделиться

Один переносимый (при условии, что 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.

0
ответ дан 6 December 2019 в 06:02
поделиться

Оператор двойной скобки - это расширенная версия команды 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 - самая распространенная и наиболее широко поддерживаемая оболочка, но цена, которую вы платите за переносимость - это потеря таких вещей, как =~.

9
ответ дан 6 December 2019 в 06:02
поделиться

Еще один (вполне) переносимый способ сделать это ...

if test "$word" != "`printf "%s" "$word" | tr -dc '[[:alpha:]]'`"; then
   echo invalid
fi
1
ответ дан 6 December 2019 в 06:02
поделиться

Игра с расширением параметров 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
)
0
ответ дан 6 December 2019 в 06:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: