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


1

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

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

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

哪个其他解决方案允许我var3不创建任何文件?


一些额外的提示...享受超级用户和bash...
哈斯图尔

Answers:


2

有很多方法......

  • 您可以使用sorttr unique并且paste$()执行他们“在变量变换输出”

    #!/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,

谢谢!完美地考虑特殊字符。
Lejour

@Lejour欢迎您的到来.​​.....欢迎使用SuperUser。即使其他答案似乎也有效。尝试并提供您认为正确且有用的答案。选择您喜欢的那个作为您的问题的答案并享受该网站。
哈斯图尔

1

我没有时间进行全面解释,但是:

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

1

另外一个选项:

#!/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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.