bash、破折号和字符串比较
Posted
技术标签:
【中文标题】bash、破折号和字符串比较【英文标题】:bash, dash and string comparison 【发布时间】:2010-11-08 13:20:54 【问题描述】:我正在尝试在一个简单的 shell 脚本中比较两个字符串。
我用的是/bin/sh
而不是/bin/bash
,经过无数小时的调试,结果是sh(实际上是dash)无法处理这段代码:
if [ "$var" == "string" ]
then
do something
fi
什么是使用/bin/sh
比较字符串的可移植方式?我知道我总是可以通过使用 != 来做相反的事情,但我想知道一种更清洁、更便携的方式。
【问题讨论】:
您可以使用[[ $var == "string" ]]
,这是 POSIX,但可选(afaik)。或者您使用 [ "$var" = "string" ]
。注意单括号版本中变量周围的""
:如果$var
为空,则需要它
重要的部分是 litb 提到的 $var
周围的引号。如果没有引号,[ $var = "value" ]
将变为 [ = "value" ]
,这会使 shell 非常混乱。否则,当您遇到空变量时,您可能会看到类似 "[: =: unary operator expected" 的错误。
我了解“$var” vs. $var,我的问题是 == vs. =
[[ ]] 被 POSIX 保留,但根本没有定义。它只是保留,因为我认为这是 Korn 的一项功能。
【参考方案1】:
dash
是一个非常严格的 POSIX shell,如果它可以在dash
中运行,那么几乎可以肯定它可以在其他 POSIX shell 中运行。
试试:
if [ "$var" = "string" ]
then
some_command
fi
【讨论】:
如果您在想“这里与问题中的语法有什么区别”:它使用=
而不是==
在本例中如何使用通配符?我试过 if [ "$OSTYPE" = "linux"* ];然后但它没有得到linux-arm,例如......【参考方案2】:
为什么您的脚本甚至有可能被“错误”的 shell 运行?我认为您可以通过在脚本顶部使用标准 sh-bang 行来将其作为产品的先决条件:
#!/bin/bash
即使用户使用不同的 shell,其他 shell 通常仍然存在,如果没有,只需抱怨并声明它们是 pre-req。
与特定内核级别或 awk 的存在可以作为前置请求完全相同的方式。
对于您的具体问题,我相信 sh
和 bash
都允许将单个 '=' 用于字符串比较 - 这是 POSIX 行为:
if [ "a" = "a" ] ; then
echo yes
fi
yes
【讨论】:
“为什么你的脚本甚至有可能被“错误”的 shell 运行?” - 是否可以控制 Autoconf 使用哪个 shell? (这就是我寻找答案的原因)【参考方案3】:使用=
代替==
。比较由 test(1) 处理。 /usr/bin/[
通常是指向 /usr/bin/test
的链接。唯一的区别是,如果您在 shell 脚本中使用[
,那么]
也是必需的。
请注意,bash 有一个内置的test
/[
,所以它实际上并没有使用/usr/bin/test
。
【讨论】:
是否有关于内置 test 和单等号或双等号的官方规范?【参考方案4】:已经发布的答案肯定是正确的,但可能值得注意的是,偶尔参数扩展可以达到相同的目的,也许还有一些额外的灵活性。
% p() printf 'notvar = %b\n' "$notvar##"$string1"$string2" ;
% string1='some stuff about things\c'
% string2='some different stuff maybe'
% notvar="$string1" p
> 'some different stuff maybe'
% notvar="$string2" p
> 'some stuff about things'
好的,所以上面的内容并不是超级有用,但也考虑到您可以使用类似的方法来测试here-documents中的变量,必要时进行内联变量分配(在一定程度上......) ,甚至只是作为一种更短(更快!)的方式来编写您的第一个语句。
[ ! "$var##"string"" ] && _MATCH || _NOMATCH
甚至……
[ $#var#*"$s=string" -lt $#var ] && _SUB_STRING_TEST=TRUE
甚至可能……
% p() printf '%s is %s of %s' "$2" "$var_chk-not" "$1"
> <<HEREDOC
> $in="$1##*"$2"*"
> $in:-
> $in="$1##"$2""
> $in:-$var_chk=all
> $var_chk=some
>
> HEREDOC
%
【讨论】:
我不确定我是否看到了这些技术的巨大好处,除非你想赢得一场混淆比赛。 哇...我需要有人来 ELI5 :)【参考方案5】:你可以使用 awk
awk 'BEGIN
string1="test"
string2="tes1t"
if(s1==s2)
print "same string"
else
print "not same"
'
【讨论】:
以上是关于bash、破折号和字符串比较的主要内容,如果未能解决你的问题,请参考以下文章