2

I'm trying to filter one array from another array. That is, I'm trying to create a third array with a logical not-intersection.

The best I can tell, it appears this block of code never matches, and found remains low:

found=0
...

if [ "$flag" = "$filtered" ]; then
    found=1
fi

I've tried using == with the same result. I also tried the X trick, but that did not work either (does it even apply here?): if [ "X$flag" = "X$filtered" ].

I'm restricted to Bash 3. I'm using Bash because I somewhat know it. I'm restricted to 3 because the script runs on OS X, too. Because of Bash 3, I think I'm missing many useful functions, like HashMaps.

Why are the strings not matching?


Here is the relevant snippet. CXXFLAGS can be set by the user in his/her environment. I'm trying to remove flags that we explicitly test in our test script, like -DDEBUG, -DNDEBUG, and optimizations like -O0 and -O1.

# Respect user's preferred flags, but filter the stuff we expliclty test
FILTERED_CXXFLAGS=("-DDEBUG", "-DNDEBUG", "-O0", "-O1", "-O2", "-O3", "-Os", "-Og")
# Additional CXXFLAGS we did not filter
RETAINED_CXXFLAGS=("")

if [ ! -z "CXXFLAGS" ]; then
    TEMP_CXXFLAGS=$(echo "$CXXFLAGS" | sed 's/\([[:blank:]]*=[[:blank:]]*\)/=/g')
    IFS=' ' read -r -a TEMP_ARRAY <<< "$TEMP_CXXFLAGS"

    for flag in "${TEMP_ARRAY[@]}"
    do
        echo "Flag: $flag"
        found=0
        for filtered in "${FILTERED_CXXFLAGS[@]}"
        do
            echo "Filtered: $filtered"
            if [ "$flag" = "$filtered" ]; then
                echo "Found: $flag"
                found=1
            fi
        done
        echo "Found: $found"
        if [ "$found" -eq "0" ]; then
            echo "Retaining $flag"
            RETAINED_CXXFLAGS+=($temp)
        else
            echo "Discarding $temp"
        fi
    done
fi

Here's a trace with the echo's in place. The test data was simply export CXXFLAGS="-DNDEBUG -g2 -O3 -mfpu=neon"

Flag: -DNDEBUG
Filtered: -DDEBUG,
Filtered: -DNDEBUG,
Filtered: -O0,
Filtered: -O1,
Filtered: -O2,
Filtered: -O3,
Filtered: -Os,
Filtered: -Og
Found: 0
Retaining -DNDEBUG
Flag: -g2
Filtered: -DDEBUG,
Filtered: -DNDEBUG,
Filtered: -O0,
Filtered: -O1,
Filtered: -O2,
Filtered: -O3,
Filtered: -Os,
Filtered: -Og
Found: 0
Retaining -g2
Flag: -O3
Filtered: -DDEBUG,
Filtered: -DNDEBUG,
Filtered: -O0,
Filtered: -O1,
Filtered: -O2,
Filtered: -O3,
Filtered: -Os,
Filtered: -Og
Found: 0
Retaining -O3
Flag: -mfpu=neon
Filtered: -DDEBUG,
Filtered: -DNDEBUG,
Filtered: -O0,
Filtered: -O1,
Filtered: -O2,
Filtered: -O3,
Filtered: -Os,
Filtered: -Og
Found: 0
Retaining -mfpu=neon

1 Answer 1

3

They don't match because FILTERED_CXXFLAGS has commas and ${TEMP_ARRAY[@]} does not:

Flag: -DNDEBUG
Filtered: -DDEBUG,
Filtered: -DNDEBUG,

If the commas are supposed to be there, then replace:

if [ "$flag" = "$filtered" ]; then

with:

if [ "$flag" = "${filtered%%,}" ]; then

Alternatively, if the commas are not supposed to be there, then the issue is with:

FILTERED_CXXFLAGS=("-DDEBUG", "-DNDEBUG", "-O0", "-O1", "-O2", "-O3", "-Os", "-Og")

One can use declare -p to see what value bash has given to a variable:

$ declare -p FILTERED_CXXFLAGS
declare -a FILTERED_CXXFLAGS='([0]="-DDEBUG," [1]="-DNDEBUG," [2]="-O0," [3]="-O1," [4]="-O2," [5]="-O3," [6]="-Os," [7]="-Og")'

One can see that the commas are included in the value of each element. While many languages require array elements to be separated by commas, Unix shell does not. Instead it treats them as part of the value of the array elements. Thus, replace the above definition with:

FILTERED_CXXFLAGS=("-DDEBUG" "-DNDEBUG" "-O0" "-O1" "-O2" "-O3" "-Os" "-Og")
0

You must log in to answer this question.