Проверка строки, чтобы увидеть, содержит ли она числовой символ в UNIX - PullRequest
7 голосов
/ 20 июля 2010

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

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

Это работает нормально, но теперь мне нужно проверить, читается ли слово, содержит ли оно ничего, кроме букв, и есть ли в нем числовые символы при печати "Неверный ввод!" сообщение и попросите их ввести его снова. Я предполагал, что регулярные выражения с оператором if будут простым способом сделать это, но я не могу понять, как их использовать в UNIX, так как я привык к их Java-приложению. Буду признателен за любую помощь в этом, так как я не смог найти помощь при поиске, так как все решения с регулярными выражениями в linux, которые я нашел, имели дело только с тем, было ли оно все числовым или нет.

Ответы [ 7 ]

17 голосов
/ 20 июля 2010

Еще один подход.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
9 голосов
/ 20 июля 2010

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

3 голосов
/ 20 июля 2010

Если вы пытаетесь написать переносимый код оболочки, ваши возможности для работы со строками ограничены. Вы можете использовать шаблоны сглаживания оболочки (которые намного менее выразительны, чем регулярные выражения) в конструкции 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 локалей диапазоны символов, такие как A-Z, не имеют «очевидного» значения. Я предполагаю, что вы хотите только буквы ASCII; если вам также нужны буквы с диакритическими знаками, не меняйте LC_COLLATE и заменяйте A-Za-z на [:alpha:] (поэтому весь шаблон становится *[![:alpha:]]*).

Полные регулярные выражения см. В команде expr. EDIT : обратите внимание, что 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», тогда как обычный $foo означает «принять значение foo, разбить его на отдельные слова, где оно содержит пробел, и относитесь к каждому слову как к шаблону и пытайтесь расширить его ». (На самом деле, если вы уже проверили, что $word содержит только буквы, оставление кавычек не принесет никакого вреда, но требуется больше времени, чтобы подумать об этих особых случаях, чем просто ставить кавычки каждый раз.)

1 голос
/ 20 июля 2010

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

if test "$word" != "`printf "%s" "$word" | tr -dc '[[:alpha:]]'`"; then
   echo invalid
fi
0 голосов
/ 21 декабря 2013

Все ответы, похоже, основаны на том факте, что единственными недопустимыми символами являются цифры. В начальных вопросах говорится, что им нужно проверить, что строка содержит «только буквы».

Я думаю, что лучший способ сделать это -

nonalpha=$(echo "$word" | sed 's/[[:alpha:]]//g')
if [[ ${#nonalpha} -gt 0 ]]; then
    echo "Invalid character(s): $nonalpha"
fi

Если вы нашли эту страницу в поиске способа обнаружения нецифровых символов в вашей строке (как я!) Замените [[: alpha:]] на [[: digit:]].

0 голосов
/ 20 июля 2010

Игра с расширением параметров 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 голосов
/ 20 июля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...