Bash删除多个数组上的字符串

时间:2011-12-10 00:13:52

标签: arrays string bash

我的bash中有两个数组,每个都包含文件。在我的循环中,有时文件会被删除。每当发生这种情况时,其中一个数组显示旧状态,另一个数组显示新状态。我如何设法显示它们之间的差异,例如: G。哪个文件确切删除了?顺便说一句,没有其他方法可以找到。

以下是一个例子:

arr_a=( file1.txt file2.txt file3.txt )
arr_b=( file1.txt file3.txt )

#Now the output should be file2.txt

我想到了一些好莱坞echo ${arr_a[@]#arr_b[@]},但这不起作用。 (这导致arr_a完全输出。)

3 个答案:

答案 0 :(得分:1)

这个有点复杂但在数组不保持相关性的情况下会起作用。它将较大数组的所有元素排序为与较短数组中的元素相关联,然后在较大数组中打印其余元素(它适用于数组的副本)。未经充分测试:

#!/bin/bash
arr_a=( file1.txt file2.txt file3.txt )
arr_b=( file1.txt file3.txt )

sortarr() {
    local sorted=( ${!1} ) sortby=( ${!2} )
    local length=${#sorted[@]} i=${#sortby} matches
    while (( i-- )); do
        [[ ! "${sorted[@]}" =~ ${sortby[$i]} ]] && continue
        sorted=( ${sorted[@]//$BASH_REMATCH/} )
        printf -v matches '%*s' $(( $length - ${#sorted[@]} ))
        sorted=( ${matches// /$BASH_REMATCH }${sorted[@]} )
    done
    for (( i=${#sortby[@]}; i<${#sorted[@]}; i++ )); do
        echo ${sorted[$i]}
    done
}

if (( ${#arr_a[@]} > ${#arr_b[@]} )); then
    sortarr arr_a[@] arr_b[@]
else
    sortarr arr_b[@] arr_a[@]
fi

答案 1 :(得分:0)

@David:你基本上需要的是两组之间的区别。使用一点python可以更轻松地完成此操作,如下面的方法0所示。方法-1和2只是使用Bash索引和稀疏数组的两种变体。以下每种方法的输出均为file2.txt

方式-0:

#!/bin/bash

arr_a=( file1.txt file2.txt file3.txt )
arr_b=( file1.txt file3.txt )

echo -e "${arr_a[@]} \n ${arr_b[@]}" | python -c '\
    a=set(raw_input().strip().split());\
    b=set(raw_input().strip().split());\
    (x,y)=(a,b) if len(a)>len(b) else (b,a);\
    print "".join(list(x-y));'

方式-1:

#!/bin/bash

arr_a=( file1.txt file2.txt file3.txt )
arr_b=( file1.txt file3.txt )
i=0

for a in ${arr_a[@]}
do
    AinB=0
    for b in ${arr_b[@]}
    do
        if [[ $a == $b ]]
        then
            AinB=1
        fi
    done

    if [[ AinB -eq 0 ]]
    then
        arr_c[$((i++))]=$a
    fi
done

echo ${arr_c[@]}

方式-2:

#!/bin/bash

arr_a="file1.txt file2.txt file3.txt"
arr_b="file1.txt file3.txt"
arr_c=""

for a in $arr_a
do
    isPresentInB=0
    for b in $arr_b
    do
        if [[ $a == $b ]]
        then
            isPresentInB=1
            break
        fi
    done

    if [[ $isPresentInB -eq 0 ]]
    then
        arr_c="$arr_c $a"
    fi
done

echo $arr_c

答案 2 :(得分:0)

这可能对您有用:

arr_a=(file1.txt file2.txt file3.txt)
arr_b=(file1.txt file3.txt)
answer=$(comm -3 <(printf "%s\n" "${arr_a[@]}") <(printf "%s\n" "${arr_b[@]}")
echo "$answer"
file2.txt

或许明智的做法是更加强大:

arr_answer=($(comm -3 <(printf "%s\n" "${arr_a[@]}") <(printf "%s\n" "${arr_b[@]}") | paste -sd' '))
((${#arr_answer[@]}==1)) && echo "$arr_answer" || echo "oops! wrong answer"