【问题标题】:How to compare strings in Bash如何在 Bash 中比较字符串
【发布时间】:2011-01-15 06:38:36
【问题描述】:

如何将变量与字符串进行比较(如果它们匹配则执行某些操作)?

【问题讨论】:

标签: string bash


【解决方案1】:

在 if 语句中使用变量

if [ "$x" = "valid" ]; then
  echo "x has the value 'valid'"
fi

如果您想在它们不匹配时做某事,请将= 替换为!=。您可以在各自的文档中阅读有关 string operationsarithmetic operations 的更多信息。

为什么我们在 $x 周围使用引号?

您需要 $x 周围的引号,因为如果它为空,您的 Bash 脚本会遇到如下所示的语法错误:

if [ = "valid" ]; then

== 运算符的非标准使用

请注意,Bash 允许 == 用于与 [ 相等,但 this is not standard

使用第一种情况,其中$x 周围的引号是可选的:

if [[ "$x" == "valid" ]]; then

或使用第二种情况:

if [ "$x" = "valid" ]; then

【讨论】:

  • 这与Unexpected operator error 中给出的已接受答案有何关系?我在使用[ "$1" == "on" ] 时遇到了同样的错误。将其更改为 [ "$1" = "on" ] 解决了问题。
  • 空格是必须的。
  • @JohnFeminella 在 bash 脚本中编写时,它应该有一个 = 而不是两个。
  • @user13107 那么您可能使用的是sh,而不是bash。这是一个关于bash的问题。
  • 值得注意的是,您不能使用[ $x -eq "valid" ]-eq 是整数的比较运算符,而不是字符串。
【解决方案2】:

或者,如果您不需要 else 子句:

[ "$x" == "valid" ] && echo "x has the value 'valid'"

【讨论】:

  • 如果你确实需要一个 else 子句并且想要做一个疯狂的单行: [ "$x" == "valid" ] && echo "valid" ||回显“无效”
  • @MattWhite:这通常是个坏主意,因为echo 可能会失败。
  • @gniourf_gniourf,没问题,使用[ "$X" == "valid" ] || ( echo invalid && false ) && echo "valid"
  • @12431234123412341234123 { echo invalid && false; }( echo invalid && false ) 更有效,因为它避免了为不必要的子shell 付费。
  • 在 POSIX sh 中,== 代替 = 是未定义的。 [SC2039]
【解决方案3】:
a="abc"
b="def"

# Equality Comparison
if [ "$a" == "$b" ]; then
    echo "Strings match"
else
    echo "Strings don't match"
fi

# Lexicographic (greater than, less than) comparison.
if [ "$a" \< "$b" ]; then
    echo "$a is lexicographically smaller then $b"
elif [ "$a" \> "$b" ]; then
    echo "$b is lexicographically smaller than $a"
else
    echo "Strings are equal"
fi

注意事项:

  1. if[] 之间的空格很重要
  2. &gt;&lt; 是重定向运算符,因此对于字符串,请分别使用 \&gt;\&lt; 对其进行转义。

【讨论】:

  • 感谢字符串字母顺序比较
  • 我的问题是 $a 实际上有 " " 围绕它作为字符串文字值的一部分,因此我必须使用转义字符到 $b 来比较这些值。我在运行 bash -x ./script.sh 后能够找到这个,-x 标志允许您查看每次执行的值并有助于调试。
  • 请注意,字母顺序比较不是 POSIX 标准化的,因此不能保证在非 GNU 平台/非 bash shell 上工作。只有pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html 处的操作才能保证是可移植的。
【解决方案4】:

要将字符串与通配符进行比较,请使用:

if [[ "$stringA" == *"$stringB"* ]]; then
  # Do something here
else
  # Do something here
fi

【讨论】:

  • 重要的是通配符只能用在右边!还要注意通配符周围缺少的"。 (顺便说一句:通配符 +1!)
  • 扩展$stringB必须被引用(顺便说一下,左侧不需要被引用):if [[ $stringA = *"$stringB"* ]]; then
  • 我正在尝试对文件路径中的文件名使用相同的通配符逻辑。但这对我不起作用。尝试了此处提供的所有不同的通配符字符串。但它总是去其他情况。在我的例子中,stringA 是文件路径 /tmp/file,而 stringB 是“file”。
【解决方案5】:

我不得不在某一点上不同意其中一个 cmets:

[ "$x" == "valid" ] && echo "valid" || echo "invalid"

不,这不是一个疯狂的单行者

它只是看起来像一个,嗯,外行......

在某种程度上,它使用通用模式作为一种语言;

在你学会了语言之后。

其实挺好读的

这是一个简单的逻辑表达式,有一个特殊的部分:逻辑运算符的惰性求值。

[ "$x" == "valid" ] && echo "valid" || echo "invalid"

每一部分都是一个逻辑表达式;第一个可能是真或假,其他两个总是正确的。

(
[ "$x" == "valid" ] 
&&
echo "valid"
)
||
echo "invalid"

现在,当它被评估时,第一个被检查。如果为false,则逻辑&amp;&amp;之后的第二个操作数不相关。第一个不是真的,所以它不可能是第一个而第二个是真的。
现在,在这种情况下,逻辑的第一面 or || 为假,但如果另一面(第三部分)为真,则它可能为真。

因此将评估第三部分 - 主要将消息写入作为副作用。 (结果0为真,这里我们不使用)

其他情况类似,但更简单 - 而且 - 我保证!是 - 可以 - 易于阅读!
(我没有,但我认为成为一名留着白胡子的 UNIX 资深人士对此有很大帮助。)

【讨论】:

  • ... &amp;&amp; ... || ... 通常不受欢迎(抱歉,灰胡子的 Unix 资深人士,你一直都错了),因为它在语义上不等同于 if ... then ... else ...。别担心,this is a common pitfall
  • @gniourf_gniourf OP 没有错——他们也不会像你建议的那样无知。 ... &amp;&amp; ... || ... 是一个完全有效的模式和一个常见的 bash 习惯用法。使用它确实规定了先验知识(如果听众中有初学者,请记住这一点),但 OP 有头发证明他们知道如何避免打开井盖。
  • @ebpa 如果 && 后面的语句返回 false 值怎么办,将继续执行 || 后面的语句?如果是这样,那就错了,也许这就是 gniourf 的建议
  • 我认为 echo 只是一个例子。 && 后面的语句可能仍然返回非零值
  • @gniourf_gniourf +1 用于发布 Bash Pitfalls 的链接!很有用!
【解决方案6】:

以下脚本逐行读取名为“testonthis”的文件,然后将每一行与一个简单字符串、一个带有特殊字符的字符串和一个正则表达式进行比较。如果不匹配,则脚本将打印该行,否则不打印。

Bash 中的空间非常重要。所以以下将起作用:

[ "$LINE" != "table_name" ] 

但以下不会:

["$LINE" != "table_name"] 

所以请按原样使用:

cat testonthis | while read LINE
do
if [ "$LINE" != "table_name" ] && [ "$LINE" != "--------------------------------" ] && [[ "$LINE" =~ [^[:space:]] ]] && [[ "$LINE" != SQL* ]]; then
echo $LINE
fi
done

【讨论】:

  • 使用this approach 浏览文件。也就是说,删除 UUoC 等。
  • 这并不重要,因为bash 但因为[ 实际上是一个外部二进制文件(如which [ 产生类似/usr/bin/[ 的东西)
【解决方案7】:

你也可以使用 case/esac:

case "$string" in
 "$pattern" ) echo "found";;
esac

【讨论】:

  • 这是等价还是包含?
  • @ytpillai ,它是等价的。请记住,您可以在) 之前使用| 分隔模式。 in 语句相当于if 语句中的then。你可能会争辩说它适用于一个模式列表,如果你来自 Python,每个列表都有自己的声明。不像substring in string,而是for item in list。如果您想要 else 条件,请使用 * 作为最后一条语句。它在第一次相遇时返回。
【解决方案8】:

Bash 4+ 示例。注意:当单词包含空格等时,不使用引号会导致问题。始终在 Bash、IMO 中引用。

以下是 Bash 4+ 中的一些示例:

示例 1,检查字符串中的“是”(不区分大小写):

    if [[ "${str,,}" == *"yes"* ]] ;then

示例 2,检查字符串中的“是”(不区分大小写):

    if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then

示例 3,检查字符串中的“是”(区分大小写):

     if [[ "${str}" == *"yes"* ]] ;then

示例 4,检查字符串中的“是”(区分大小写):

     if [[ "${str}" =~ "yes" ]] ;then

示例 5,完全匹配(区分大小写):

     if [[ "${str}" == "yes" ]] ;then

示例 6,完全匹配(不区分大小写):

     if [[ "${str,,}" == "yes" ]] ;then

示例 7,完全匹配:

     if [ "$a" = "$b" ] ;then

享受吧。

【讨论】:

  • 对我来说(mac GNU bash 版本 4.4.12(1)-release x86_64-apple-darwin17.0.0),我必须使用 if [ "$a"="$b" ] 否则它不起作用......可以' t 在等号周围有空格
【解决方案9】:

如果输入只有几个有效条目,我可能会使用正则表达式匹配。例如。只有“开始”和“停止”是有效的动作。

if [[ "${ACTION,,}" =~ ^(start|stop)$ ]]; then
  echo "valid action"
fi

请注意,我使用双逗号将变量 $ACTION 小写。另请注意,这不适用于过于陈旧的 bash 版本。

【讨论】:

    【解决方案10】:

    我这样做的方式与 Bash 和 Dash (sh) 兼容:

    testOutput="my test"
    pattern="my"
    
    case $testOutput in (*"$pattern"*)
        echo "if there is a match"
        exit 1
        ;;
    (*)
       ! echo there is no coincidence!
    ;;esac
    

    【讨论】:

    • 使用前面的( 和不使用有什么区别?
    【解决方案11】:

    您有比较问题吗? (如下所示?)

    var="true"
    if [[ $var == "true" ]]; then
      # It should be working, but it is not...
    else
      # It is falling here...
    fi
    

    尝试像 =~ 运算符(正则表达式运算符),它可能会工作:

    var="true"
    if [[ $var =~ "true" ]];then
      # Now it works here!!
    else
      # No more inequality
    fi
    

    【讨论】:

    • 您能否链接到=~ 运算符的(官方)文档?请通过editing (changing) your answer 回复,而不是在 cmets 中(without "Edit:"、"Update:" 或类似的 - 答案应该看起来像是今天写的)。
    猜你喜欢
    • 2015-08-30
    • 2012-03-02
    • 2013-02-21
    • 2021-10-29
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    相关资源
    最近更新 更多