我是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中找到了正则表达式的所有解决方案,我发现它只是处理它是否全部是数字。
答案 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
个字符会阻止$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
只包含字母,那么留下引号不会造成任何伤害,但是考虑这些特殊情况需要花费更多时间而不是每次都使用引号。)
答案 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:]]。