AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 718976
Accepted
Zaida
Zaida
Asked: 2022-09-28 21:32:31 +0800 CST2022-09-28 21:32:31 +0800 CST 2022-09-28 21:32:31 +0800 CST

将布尔比较中的值分配给变量

  • 772

我有一个脚本,我需要在其中对字符串变量的内容进行所有可能的比较。每种组合都需要对变量内容采用不同的方法,因此如下所示:

if $a contains "a" AND "b" AND "c"; then do x
elif $a contains "a" AND "b" but NOT "c"; then do y
elif $a contains "b" AND "c" but NOT "a"; then do z
...

据我所知,这样做的方法是构造一个像这样的 if 条件:

if [[ $A == *"b"* ]] && [[ $A == *"c"* ]] && [[ $A == *"d"* ]]
elif [[ $A == *"b"* ]] && [[ $A == *"c"* ]]
elif [[ $A == *"c"* ]] && [[ $A == *"d"* ]]
elif [[ $A == *"b"* ]] && [[ $A == *"d"* ]]
elif [[ $A == *"b"* ]]
elif [[ $A == *"c"* ]]
elif [[ $A == *"d"* ]]
fi

但这当然太复杂了,因为我的变量($A)和子字符串(b,c,d)的名称比这长得多。所以我想看看是否有办法将条件表达式的内容保存到变量中:

contains_b= *a condition for [[ $A == *"b"* ]]*; echo $contains_b-> 真 | 错误的

我只在这里找到了回复[ contains_b=$(! [ "$A" = *"b"* ]; echo $?)]; 但是,$contains_b -> 0在随后的条件句中不起作用,因为:

if $contains_b; then do x; fi->bash: [0]: command not found

所以我能想到的唯一解决方案是手动完成:

if [[ $A == *"b"* ]]; then
    contains_b=true
else
    contains_b=false
fi

但是,我最终会执行三个 if 语句来获取三个变量,以及每个不同组合的其他 7 个比较。

我想知道是否有不同/更有效的方法。如果没有,您对进行这些多重比较的另一种方法有什么建议吗?我觉得我把它弄得太复杂了......

感谢您的任何帮助。

bash shell-script
  • 4 4 个回答
  • 570 Views

4 个回答

  • Voted
  1. Best Answer
    Kusalananda
    2022-09-28T22:44:41+08:002022-09-28T22:44:41+08:00

    创建一个二进制掩码,然后对其进行操作。这样做的好处是每个测试只执行一次,并将测试与对测试结果的操作分开。

    请注意,代码将模式用作扩展的正则表达式。要将它们作为字符串进行比较,请使用

    [[ $string == *"$pattern"* ]]
    

    代替

    [[ $string =~ $pattern ]]
    

    在下面的代码中。

    patterns=( a b c )
    string='abba'
    
    mask=0; i=0
    for pattern in "${patterns[@]}"; do
            if [[ $string =~ $pattern ]]; then
                    # setting the i:th bit from the right to one
                    mask=$(( mask | (1 << i) ))
            fi
            i=$(( i + 1 ))
    done
    
    case $mask in
            0) echo no match ;;
            1) echo first pattern matched ;;
            2) echo second pattern matched ;;
            3) echo first and second pattern matched ;;
            4) echo third pattern matched ;;
            5) echo first and third pattern matched ;;
            6) echo second and third pattern matched ;;
            7) echo all patterns matched ;;
            *) echo error
    esac
    

    或者,使用带有 1 和 0 的字符串掩码(0 表示不匹配,1 表示匹配)。请注意,mask下面的字符串与上面代码中使用的数字的实际二进制表示相反。

    patterns=( a b c )
    string='abba'
    
    unset -v mask
    for pattern in "${patterns[@]}"; do
            ! [[ $string =~ $pattern ]]
            # string concatenation of the exit status of the previous command
            mask+=$?
    done
    
    case $mask in
            000) echo no match ;;
            100) echo first pattern matched ;;
            010) echo second pattern matched ;;
            110) echo first and second pattern matched ;;
            001) echo third pattern matched ;;
            101) echo first and third pattern matched ;;
            011) echo second and third pattern matched ;;
            111) echo all patterns matched ;;
            *) echo error
    esac
    

    每个脚本的输出将是

    first and second pattern matched
    

    ...因为字符串abba匹配前两个模式,a并且b.

    • 8
  2. Stéphane Chazelas
    2022-09-28T23:26:08+08:002022-09-28T23:26:08+08:00

    这里使用bash4.0或更高版本或mkshR40或更高版本,您可以通过两个case语句完成所有操作:

    a=n b=n c=n
    case $string in
      (*a*) a=y ;;&
      (*b*) b=y ;;&
      (*c*) c=y
    esac
    case $a$b$c in
      (nnn) echo none   ;;
      (ynn) echo a only ;;
      (yyn) echo ab     ;;
      (yyy) echo all    ;;
        (*) echo other
    esac
    

    's is的zsh等价物bash;;&;|也受mksh.

    • 6
  3. muru
    2022-09-28T22:07:21+08:002022-09-28T22:07:21+08:00

    我只找到了响应 [这里][1] [ contains_b=$(! [ "$A" = *"b"* ]; echo $?)]; 但是,$contains_b -> 0在随后的条件句中不起作用,因为:

    if $contains_b; then do x; fi->bash: [0]: command not found

    一旦你得到一个数字的结果,你应该对它使用算术运算,而不是把它作为命令运行:

    contains_a=$(! [[ $A == *$pattern_a* ]]; echo $?)
    contains_b=$(! [[ $A == *$pattern_b* ]]; echo $?)
    contains_c=$(! [[ $A == *$pattern_c* ]]; echo $?)
    
    if (( contains_a && contains_b && contains_c )); then
        echo all
    elif (( contains_a && contains_b )); then
        echo ab
    ...
    fi
    
    • 2
  4. QuartzCristal
    2022-09-29T08:55:31+08:002022-09-29T08:55:31+08:00

    =~可以通过在 bash 中使用正则表达式匹配测试每个可能的匹配模式一次来构建二进制数。为了以正确的顺序构建二进制数(MSB 保留并对应于最后执行的测试),我们需要将(否定的)退出代码添加到变量中。

    #!/bin/bash --
    
    string=${1:-"abba"}
    
    patterns=( a b c )
    
    unset bin
    for re in "${patterns[@]}"; do
        ! [[ $string =~ $re ]]; bin="$?$bin"
    done
    
    case $((2#$bin)) in
            0) echo no match ;;
            1) echo first pattern matched ;;
            2) echo second pattern matched ;;
            3) echo first and second pattern matched ;;
            4) echo third pattern matched ;;
            5) echo first and third pattern matched ;;
            6) echo second and third pattern matched ;;
            7) echo all patterns matched ;;
            *) echo error
    esac
    
    

    只是先前答案的替代解决方案。

    • 1

相关问题

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • MySQL Select with function IN () with bash array

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve