Regex 在UNIX中检查字符串是否包含数字字符
我是UNIX新手,今天才开始使用它,但对Java很有经验,并拥有以下代码:Regex 在UNIX中检查字符串是否包含数字字符,regex,string,bash,unix,if-statement,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 这很好,但我现在需要做的是检查何时读取单词,它只包含字母,并且在打印的“Invalid input!”消息中是否包含数字字符,并要求他们再次输入。我假设带有if语句的正则表达式是实现这一点的简单方法,但我无
#/bin/bash
echo "Please enter a word:"
read word
grep -i $word $1 | cut -d',' -f1,2 | tr "," "-"> output
这很好,但我现在需要做的是检查何时读取单词,它只包含字母,并且在打印的“Invalid input!”消息中是否包含数字字符,并要求他们再次输入。我假设带有if语句的正则表达式是实现这一点的简单方法,但我无法理解如何在UNIX中使用它们,因为我已经习惯了它们的Java应用程序。对此,我将不胜感激,因为我在搜索时找不到帮助,因为我在linux中找到的所有带有正则表达式的解决方案只有在它们都是数字或不是数字的情况下才能处理。一种可移植的(假设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 For 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是一个较新的shell,并非在所有版本的UNIX上都可用——尽管“较新”的意思是“仅在后真空管时代开发”,而“并非所有版本的UNIX”的意思是旧版本的Solaris和HP-UX
在我看来,这是最简单的选择,而bash现在已经具备了足够的可移植性,但是如果移植到旧unix实际上很重要,那么您需要使用其他海报的sh兼容答案。sh是最常见和最广泛支持的shell,但是您为可移植性付出的代价正在失去一些东西,如
=~
如果您试图编写可移植的shell代码,那么字符串操作的选项是有限的。您可以在案例
构造中使用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
EDIT:设置LC\u COLLATE
是必要的,因为在大多数非C
地区,像A-Z
这样的字符范围没有“明显”的含义。我假设您只需要ASCII字母;如果您还想要带变音符号的字母,请不要更改LC\u-COLLATE
,并将A-Za-z
替换为[:alpha:][/code>(因此整个模式变为*[![:alpha:][]*
)
有关完整的regexp,请参阅expr
命令EDIT:注意,expr
与其他一些基本shell工具一样,在某些特殊字符串中存在陷阱;下面的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版本,那么还有其他选项,例如[[…]]
条件命令的=~
操作符
注意,您的最后一行有一个bug,第一个命令应该是
grep -i "$word" "$1"
引用是因为有点反直觉,“$foo”
表示“名为foo
的变量的值”,而普通的$foo
表示“取foo
的值,将其拆分为包含空格的单独单词,并将每个单词视为一个全局模式并尝试扩展它”。(事实上,如果你已经检查过,$word
只包含字母,留下引号不会有任何伤害,但考虑这些特殊情况比每次都放引号要花更多的时间。)还有另一种方法。如果找到匹配项,Grep将退出0
,因此您可以测试退出代码:
echo "${word}" | grep -q '[0-9]'
if [ $? = 0 ]; then
echo 'Invalid input'
fi
这是兼容的
结合Daenyth和John的建议,这将成为
if echo "${word}" | grep '[0-9]' >/dev/null; then
echo 'Invalid input'
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
)
还有一种(相当)便携的方法
if test "$word" != "`printf "%s" "$word" | tr -dc '[[:alpha:]]'`"; then
echo invalid
fi
每个人的答案似乎都基于这样一个事实:唯一的无效字符是数字。最初的问题说明他们需要检查字符串是否包含“除字母外的其他内容”
我认为最好的办法是
nonalpha=$(echo "$word" | sed 's/[[:alpha:]]//g')
if [[ ${#nonalpha} -gt 0 ]]; then
echo "Invalid character(s): $nonalpha"
fi
如果您发现此页面正在寻找一种方法来检测字符串中的非数字字符(就像我所做的!),请将[[:alpha:]替换为[[:digit:].假设bash kitty?这太残忍了。-q
到grep在GNU之外是不可移植的。如果您想要完全的可移植性(使用sh的唯一原因),请使用/dev/null 2>&1
@Daenyth您完全正确,我甚至在我的系统上试用了它,然后在发布答案时添加了-q
。看来我做GNU的时间太长了。你可以通过改变cmd;如果[$?=0];然后
到如果cmd;然后,
@John,我想你错过了“我是UNIX新手”,这是聪明之前的明确性。@Anders这与聪明无关,这与做foo=returnTrue()之间的区别是一样的;if(foo==true)
和if(returnTrue())
您列出的案例对于非ascii非数字输入失败。@Daenyth:true,所有使用A-Za-z
的解决方案都假定为ascii区域设置。因此,让我添加一个脚注:如果您想允许您所在区域中的所有字母(包括带变音符号的字母),请将a-Za-z
替换为[:alpha://code>(case
,expr
,grep
,…)(是的,括号内有括号)。如果您只需要ASCII字母,请在脚本开头附近放置export LC\u COLLATE=C
。更简单的解决方案是将其反转——测试它是否包含[^0-9]
。白名单比黑名单容易。@Daenyth:这不是白名单/黑名单问题:[^0-9]
会接受非字母数字,而我认为locky28意味着拒绝它们。如果有更好的反对意见就好了