检查字符串以查看它是否包含UNIX中的数字字符

时间:2010-07-19 20:27:57

标签: regex string bash unix if-statement

我是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 个答案:

答案 0 :(得分:17)

又一种方法。如果找到匹配项,Grep会以0退出,因此您可以测试退出代码:

echo "${word}" | grep -q '[0-9]'
if [ $? = 0 ]; then
    echo 'Invalid input'
fi

这是/bin/sh兼容的。


纳入Daenyth和John的建议,这就变成了

if echo "${word}" | grep '[0-9]' >/dev/null; then
    echo 'Invalid input'
fi

答案 1 :(得分:9)

双括号运算符是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是一个较新的shell,并不适用于所有类型的UNIX - 虽然“更新”我的意思是“最近才在真空管后时代开发”和“并非所有版本的UNIX”我的意思是旧版本的遗物Solaris和HP-UX。

在我看来,这是最简单的选项,bash目前很容易移植,但如果可移植到旧UNIX实际上很重要,那么你需要使用其他海报的sh兼容答案。 sh是最常见和最广泛支持的shell,但是为可移植性付出的代价正在丢失=~之类的内容。

答案 2 :(得分:3)

如果您正在尝试编写可移植的shell代码,则字符串操作的选项会受到限制。您可以在case构造中使用shell globbing模式(表达式比regexp低得多):

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

编辑:设置LC_COLLATE是必要的,因为在大多数非C语言环境中,A-Z等字符范围没有“明显”含义。我假设你只想要ASCII字母;如果您还想要带有变音符号的字母,请不要更改LC_COLLATE,并将A-Za-z替换为[:alpha:](因此整个模式将变为*[![:alpha:]]*)。

有关完整的正则表达式,请参阅expr命令。 编辑:请注意expr与其他几个基本shell工具一样,有一些特殊字符串存在缺陷;下面的z个字符会阻止$wordexpr解释为保留字。

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只包含字母,那么留下引号不会造成任何伤害,但是考虑这些特殊情况需要花费更多时间而不是每次都使用引号。)

答案 3 :(得分:1)

另一种(非常)便携的方式......

if test "$word" != "`printf "%s" "$word" | tr -dc '[[:alpha:]]'`"; then
   echo invalid
fi

答案 4 :(得分:0)

一个便携式(假设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字符串操作。

答案 5 :(得分:0)

使用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
)

答案 6 :(得分:0)

每个人的答案似乎都是基于这样一个事实,即唯一无效的字符是数字。最初的问题表明他们需要检查字符串是否只包含“字母”。

我认为最好的方法是

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

如果您发现此页面正在寻找一种方法来检测字符串中的非数字字符(就像我做的那样!)将[[:alpha:]]替换为[[:digit:]]。