bash - 查找两个变量之间的差异

bash - 查找两个变量之间的差异

我有两个变量:var1="1, 2, 3, 4"var2="3, 4, 5, 6"
我想得到一个新的,变量3$var1,包含和之间的差异$var2
预期结果应该是var3=1, 2, 5, 6

我尝试过diff但输出不是我想要的:

diff <(echo "$var1") <(echo "$var2")
1c1
< 1, 2, 3, 4
---
> 3, 4, 5, 6

var3还有哪种解决方案允许我在不创建任何文件的情况下实现此目的?

答案1

有很多方法...

  • 您可以使用sorttr uniquepaste$()来执行它们,“将输出转换为变量”

    #!/bin/bash
    var1="1, 2, 3, 4"; var2="3, 4, 5, 6"
    var3=$(echo " ${var1}, ${var2}" | tr ',' '\n' | sort | uniq -u | paste -sd,)
    echo $var3
    
    1, 2, 5, 6
    

    对于前面的每个命令,你可以使用例如阅读更多内容man sort

  • 您可以在 bash 数组中转换变量并对其进行操作(请将以下内容作为提示,因为有无数种方法可以实现它......)

    #!/bin/bash#!/bin/bash
    var1="1, 2, 3, 4"; var2="3, 4, 5, 6"
    
    # here you transform the variable in array
    IFS=',' read -ra ADDR <<< "$var1"    
    IFS=',' read -ra ADDR2 <<< "$var2"
    
    # then for each element in the 1st array you search if in the 2nd too
    SEP=""; var3=""
    for i in "${ADDR[@]}"; do
      Found=0
      for j in "${ADDR2[@]}"; do
          [[ "$i" -eq "$j" ]] && Found=1
      done 
      [[ $Found == 0 ]]  && { var3="$var3$SEP$i" ; SEP=", "; }
    done
    
    # then for each element in the 2nd array you search if in the 1st too
    for j in "${ADDR2[@]}"; do
      Found=0
      for i in "${ADDR[@]}"; do
          [[ "$i" -eq "$j" ]] && Found=1
      done 
      [[ $Found == 0 ]]  && { var3="$var3$SEP$j" ; SEP=", "; }
    done
    
    echo $var3
    
  • 使用awk(或者准确地说gawk

    #!/bin/bash
    var1="1, 2, 3, 4"; var2="3, 4, 5, 6"
    var3=$(echo "$var1, $var2" | \
           awk -F ',' '{for (i=1;i<=NF;i++) {A[$i]++;} } 
                    END{ SEP=""; 
                         for (i in A) {if (A[i]==1){
                            printf ("%s%s", SEP,i); SEP=", "} 
                         }
                       }'
          )
    echo $var3
    

笔记:第二个和第三个输出没有排序......


更新说明: ...并且$var1$var2诡异的( :-)) 格式在逗号 ( ,) 后有空格,因此您需要特别注意所有只使用一个字符作为分隔符的命令......如果, 1第二个字符串中有一个,则此问题得到解决......您无法找到什么,man <command>您可以尝试使用man bash或使用help command...

令人厌烦

  • diff风格,本着您的尝试精神......也许您可以搜索更舒适的输出格式(man diff

    diff --ignore-all-space   \ 
         <(echo "$var1" | tr ',' '\n' ) <(echo "$var2" | tr ',' '\n')\
         | grep -v "^---" | grep -v "^[0-9c0-9]" | tr -d '<||>|| |'  \
         | paste -sd,
    

答案2

我没有时间进行完整解释,但是:

var1="1, 2, 3, 4"; var2="3, 4, 5, 6"
comm -3 <(grep -oP '\d+' <<<"$var1" | sort) <(grep -oP '\d+' <<<"$var2" | sort) |
  tr -d '\t' |
  paste -sd,
1,2,5,6

答案3

另外一个选择:

#!/usr/bin/bash

var1="1, 2, 3, 4"
var2="3, 4, 5, 6"
out=""

for num in `echo $var1,$var2 | tr -d " "| tr "," "\n " | sort | uniq | tr "\n" " "`
do
        if (`grep -v $num <<< "$var1" >/dev/null 2>&1` || `grep -v $num <<< "$var2" >/dev/null 2>&1`)
        then
                out="$out,$num"
        fi
done

echo $out | sed -e 's/,//'

然后运行

$ ./test.sh 
1,2,5,6

相关内容