【问题标题】:How do I compare strings in Bourne Shell?如何比较 Bourne Shell 中的字符串?
【发布时间】:2010-09-16 01:34:40
【问题描述】:

我需要在 shell 中比较字符串:

var1="mtu eth0"

if [ "$var1" == "mtu *" ]
then
    # do something
fi

但显然“*”在 Shell 中不起作用。有办法吗?

【问题讨论】:

    标签: shell sh posix


    【解决方案1】:

    使用 Unix 工具。程序cut 将愉快地缩短一个字符串。

    if [ "$(echo $var1 | cut -c 4)" = "mtu " ];
    

    ...应该做你想做的事。

    【讨论】:

    • 我相信既然你在这里比较两个字符串,它应该是“=”或“==”,而不是“-eq”。
    • cut -c 4 删去第四个字符:cut -c -4 删去前四个字符。
    【解决方案2】:

    bash

    最短修复:

    if [[ "$var1" = "mtu "* ]]
    

    Bash 的 [[ ]] 没有得到全局扩展,这与 [ ] 不同(由于历史原因必须这样做)。


    bash --posix

    哦,我发的太快了。 Bourne shell,而不是 Bash...

    if [ "${var1:0:4}" == "mtu " ]
    

    ${var1:0:4} 表示$var1 的前四个字符。


    /bin/sh

    啊,对不起。 Bash 的 POSIX 仿真还远远不够;真正的原始 Bourne shell 没有 ${var1:0:4}。您需要类似 mstrobl 的解决方案。

    if [ "$(echo "$var1" | cut -c0-4)" == "mtu " ]
    

    【讨论】:

    • ${var1:0:4} -- 你从哪里得到的语法?这绝对不是 POSIX。
    • 我的 cut 版本说位置从 1 开始编号。cut -c 1-4cut -c -4 在此处返回正确的值。
    • bourne/posix shell 中没有== 运算符;它是=
    • 语法$(echo $foo)也是一种BASH主义; Bourne shell 需要反引号。
    【解决方案3】:

    您可以调用expr 将字符串与Bourne Shell 脚本中的正则表达式进行匹配。以下似乎有效:

    #!/bin/sh
    
    var1="mtu eth0"
    
    if [ "`expr \"$var1\" : \"mtu .*\"`" != "0" ];then
      echo "match"
    fi
    

    【讨论】:

      【解决方案4】:

      我喜欢用 case 语句来比较字符串。

      一个简单的例子是

      case "$input"
      in
        "$variable1") echo "matched the first value" 
           ;;
        "$variable2") echo "matched the second value"
           ;;
        *[a-z]*)  echo "input has letters" 
           ;;
        '')       echo "input is null!"
           ;;
         *[0-9]*)  echo "matched numbers (but I don't have letters, otherwise the letter test would have been hit first!)"
           ;;
         *) echo "Some wacky stuff in the input!"
      esac
      

      我做过类似的疯狂的事情

      case "$(cat file)"
      in
        "$(cat other_file)")  echo "file and other_file are the same"
            ;;
        *)  echo "file and other_file are different"
      esac
      

      这也有效,但有一些限制,例如文件不能超过几兆字节,shell 根本看不到空值,所以如果一个文件充满空值而另一个文件没有,(也没有其他任何东西),这个测试不会看到两者之间有任何区别。

      我没有使用文件比较作为一个严肃的例子,只是一个例子说明 case 语句如何能够比 test 或 expr 或其他类似的 shell 表达式更灵活地进行字符串匹配。

      【讨论】:

      • 这是最快的方法。
      【解决方案5】:

      我会做以下事情:

      # Removes anything but first word from "var1"
      if [ "${var1%% *}" = "mtu" ] ; then ... fi
      

      或者:

      # Tries to remove the first word if it is "mtu", checks if we removed anything
      if [ "${var1#mtu }" != "$var1" ] ; then ... fi
      

      【讨论】:

      • 第一个接受没有尾随空格的字符串。
      【解决方案6】:

      在 Bourne shell 中,如果我想检查一个字符串是否包含另一个字符串:

      if [  `echo ${String} | grep -c ${Substr} ` -eq 1 ] ; then
      

      用两个` 反引号将echo ${String} | grep -c ${Substr} 括起来:

      检查子串是在开头还是结尾:

      if [ `echo ${String} | grep -c "^${Substr}"` -eq 1 ] ; then
      ...
      if [ `echo ${String} | grep -c "${Substr}$"` -eq 1 ] ; then
      

      【讨论】:

        【解决方案7】:

        或者,作为 =~ 运算符的示例:

        if [[ "$var1" =~ "mtu *" ]]
        

        【讨论】:

        • Bash 3.1 及更高版本具有 [[ a =~ .* ]]。但是 * 对于没有 shopt -s compat31 的 3.2 及更高版本,引号内的 * 是错误的。
        • 不是 POSIX。
        猜你喜欢
        • 1970-01-01
        • 2015-12-21
        • 2012-05-21
        • 1970-01-01
        • 2012-06-06
        • 2020-01-31
        • 1970-01-01
        • 2012-06-22
        相关资源
        最近更新 更多