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 的存在可以作为前置请求完全相同的方式。

对于您的具体问题,我相信 shbash 都允许将单个 '=' 用于字符串比较 - 这是 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、破折号和字符串比较的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Bash 中比较两个点分隔版本格式的字符串?

将变量与字符串 bash 进行比较

bash shell数值比较(-eq)与字符比较(==)的区别

bash 中的字符串比较。 [[: 未找到

sh Bash字符串比较

在bash shell 上如何按字母顺序比较两个字符串 ?