Tim*_*Tim 677 string bash comparison
我想检查字符串是否以"node"开头,例如"node001".就像是
if [ $HOST == user* ]
then
echo yes
fi
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能正确?
我还需要组合表达式来检查HOST是"user1"还是以"node"开头
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
> > > -bash: [: too many arguments
Run Code Online (Sandbox Code Playgroud)
怎么做正确?
Mar*_*off 967
Advanced Bash Scripting Guide上的这段代码说:
# The == comparison operator behaves differently within a double-brackets
# test than within single brackets.
[[ $a == z* ]] # True if $a starts with a "z" (wildcard matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).
Run Code Online (Sandbox Code Playgroud)
所以你几乎是正确的; 你需要双括号,而不是单括号.
关于你的第二个问题,你可以这样写:
HOST=user1
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
echo yes1
fi
HOST=node001
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
echo yes2
fi
Run Code Online (Sandbox Code Playgroud)
哪个会回应
yes1
yes2
Run Code Online (Sandbox Code Playgroud)
Bash的if语法很难习惯(IMO).
bra*_*ter 186
如果您正在使用最近的bash(v3 +),我建议使用bash正则表达式比较运算符=~,即
if [[ "$HOST" =~ ^user.* ]]; then
echo "yes"
fi
Run Code Online (Sandbox Code Playgroud)
匹配this or that正则表达式使用|,即
if [[ "$HOST" =~ ^user.*|^host1 ]]; then
echo "yes"
fi
Run Code Online (Sandbox Code Playgroud)
注意 - 这是'正确'的正则表达式语法.
user*意味着use和零次或多次出现r,匹配use和userrrr匹配.user.*装置user和零或更多的出现任意字符,那么user1,userX将匹配.^user.*表示匹配user.*$ HOST开头的模式.如果您不熟悉正则表达式语法,请尝试参考此资源.
注意 - 如果你将每个新问题都问为一个新问题,它会更好,它会使stackoverflow更整洁,更有用.您始终可以包含回到上一个问题的链接以供参考.
Jo *_* So 120
我总是试图坚持使用POSIX sh而不是使用bash扩展,因为脚本的一个主要点是可移植性.(除了连接程序,不替换它们)
在sh中,有一种简单的方法来检查"is-prefix"条件.
case $HOST in node*)
your code here
esac
Run Code Online (Sandbox Code Playgroud)
考虑到多大年龄,神秘和苛刻的sh(并且bash不是治愈方法:它更复杂,更不一致,更不便携),我想指出一个非常好的功能方面:虽然有一些类似的语法元素case是内置的,结果构造与任何其他工作没有什么不同.它们可以以相同的方式组成:
if case $HOST in node*) true;; *) false;; esac; then
your code here
fi
Run Code Online (Sandbox Code Playgroud)
甚至更短
if case $HOST in node*) ;; *) false;; esac; then
your code here
fi
Run Code Online (Sandbox Code Playgroud)
或者甚至更短(只呈现!为一个语言元素-但是这是不好的风格现在)
if ! case $HOST in node*) false;; esac; then
your code here
fi
Run Code Online (Sandbox Code Playgroud)
如果您喜欢明确,请构建自己的语言元素:
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
Run Code Online (Sandbox Code Playgroud)
这不是很好吗?
if beginswith node "$HOST"; then
your code here
fi
Run Code Online (Sandbox Code Playgroud)
由于sh基本上只是作业和字符串列表(以及内部进程,其中包含作业),我们现在甚至可以进行一些轻量级的函数式编程:
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
checkresult() { if [ $? = 0 ]; then echo TRUE; else echo FALSE; fi; }
all() {
test=$1; shift
for i in "$@"; do
$test "$i" || return
done
}
all "beginswith x" x xy xyz ; checkresult # prints TRUE
all "beginswith x" x xy abc ; checkresult # prints FALSE
Run Code Online (Sandbox Code Playgroud)
这很优雅.并不是说我会主张使用sh来处理任何严重的事情 - 它在现实世界的要求上打得太快(没有lambda,所以必须使用字符串.但是用字符串嵌套函数调用是不可能的,管道是不可能的......)
mar*_*ton 75
您可以只选择要检查的字符串部分:
if [ "${HOST:0:4}" = user ]
Run Code Online (Sandbox Code Playgroud)
对于您的后续问题,您可以使用OR:
if [[ "$HOST" == user1 || "$HOST" == node* ]]
Run Code Online (Sandbox Code Playgroud)
Pau*_*ce. 56
我更喜欢已发布的其他方法,但有些人喜欢使用:
case "$HOST" in
user1|node*)
echo "yes";;
*)
echo "no";;
esac
Run Code Online (Sandbox Code Playgroud)
编辑:
我已将您的备选项添加到上面的案例陈述中
在您编辑的版本中,您有太多括号.它应该如下所示:
if [[ $HOST == user1 || $HOST == node* ]];
Run Code Online (Sandbox Code Playgroud)
dhk*_*hke 31
虽然我发现这里的大多数答案都很正确,但其中许多都含有不必要的基础.POSIX参数扩展为您提供所需的一切:
[ "${host#user}" != "${host}" ]
Run Code Online (Sandbox Code Playgroud)
和
[ "${host#node}" != "${host}" ]
Run Code Online (Sandbox Code Playgroud)
${var#expr}去掉最小的前缀匹配expr的${var},并返回.因此,如果${host}没有不下手user(node), (${host#user})${host#node}是一样的${host}.
expr允许fnmatch()通配符,因此${host#node??}和朋友也一起工作.
ozm*_*zma 29
因为#在bash中有意义所以我得到了以下解决方案.
另外我更喜欢用""打包字符串来克服空间等.
A="#sdfs"
if [[ "$A" == "#"* ]];then
echo "skip comment line"
fi
Run Code Online (Sandbox Code Playgroud)
Tho*_*der 13
把事情简单化
word="appel"
if [[ $word = a* ]]
then
echo "Starts with a"
else
echo "No match"
fi
Run Code Online (Sandbox Code Playgroud)
为Mark Rushakoff的最高等级答案添加更多的语法细节.
表达方式
$HOST == node*
Run Code Online (Sandbox Code Playgroud)
也可以写成
$HOST == "node"*
Run Code Online (Sandbox Code Playgroud)
效果是一样的.只需确保通配符在引用文本之外.如果通配符在引号内,它将按字面解释(即不作为通配符).
@OP,对于你的两个问题,你可以使用case/esac
string="node001"
case "$string" in
node*) echo "found";;
* ) echo "no node";;
esac
Run Code Online (Sandbox Code Playgroud)
第二个问题
case "$HOST" in
node*) echo "ok";;
user) echo "ok";;
esac
case "$HOST" in
node*|user) echo "ok";;
esac
Run Code Online (Sandbox Code Playgroud)
或者Bash 4.0
case "$HOST" in
user) ;&
node*) echo "ok";;
esac
Run Code Online (Sandbox Code Playgroud)
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
Run Code Online (Sandbox Code Playgroud)
不起作用,因为所有[,[[并且测试识别相同的非递归语法.请参阅bash手册页中的CONDITIONAL EXPRESSIONS部分.
顺便说一句,SUSv3说
在早期提案中,从shell命令语言描述中删除了KornShell派生的条件命令(双括号[[]]).提出异议,认为真正的问题是滥用测试命令([),并将其放入shell中是解决问题的错误方法.相反,适当的文档和新的shell保留字(!)就足够了.
需要多个测试操作的测试可以在shell级别使用测试命令和shell逻辑的单独调用来完成,而不是使用容易出错的-o - test标志.
你需要这样写,但测试不支持它:
if [ $HOST == user1 -o $HOST == node* ];
then
echo yes
fi
Run Code Online (Sandbox Code Playgroud)
test uses =表示字符串相等,更重要的是它不支持模式匹配.
case/ esac对模式匹配有很好的支持:
case $HOST in
user1|node*) echo yes ;;
esac
Run Code Online (Sandbox Code Playgroud)
它具有额外的好处,它不依赖于bash,语法是可移植的.来自Single Unix规范,Shell命令语言:
case word in
[(]pattern1) compound-list;;
[[(]pattern[ | pattern] ... ) compound-list;;] ...
[[(]pattern[ | pattern] ... ) compound-list]
esac
Run Code Online (Sandbox Code Playgroud)
grep
忘记性能,这是 POSIX 并且看起来比解决方案更好case:
mystr="abcd"
if printf '%s' "$mystr" | grep -Eq '^ab'; then
echo matches
fi
Run Code Online (Sandbox Code Playgroud)
解释:
printf '%s'防止printf扩展反斜杠转义:Bash printf 逐字字符串grep -q防止匹配到 stdout 的回显:如何使用 Bash 检查文件是否包含特定字符串grep -E启用扩展正则表达式,这是我们需要的^