2

all

I got two 2D-array files to read with bash

file1.txt (nx6)

DESC1 DM1 W1 S1 CRITICAL1 GRADE1 #this line dosen't exist
EEE 1x 9 6 Y E2 
AAA X 1 2 Y E2 
C+C X 8 1 Y T1 
HHH 1x 5 5 Y T2 
III X 5 5 Y S1 
JJJ X 5 5 Y S1 
D+ X 2 3 Y T1 

file2.txt (mx3)

DESC2 W2 S2 #this line dosen't exist
AAA 1 2 
EEE 9 5 
FFF 10 7 
GGG 4 9 
III 5 5 
C+C 8 1 
D+ 2 3 
JJJ 5 5 

what I wanna do is to extract the elements inside both files then do some comparisons as following picture:

two muppets https://i.stack.imgur.com/iOFzl.png

I really wanna do in green labels is to take one element in $DESC1 and compare with whole elements in ${DESC2[@]}, if it does/dosen't find a element in ${DESC2[@]} then feedback true/false

Here is my work:

#!/bin/bash

clear

ESC=`printf "\033"`

##===================================================================##
##===================================================================##
##========== read information from file1.txt and file1.txt ==========##
##===================================================================##
##===================================================================##

idx1=0

while read -a file1array$idx1; do
    let idx1++
done < file1.txt

idx2=0

while read -a file2array$idx2; do
    let idx2++
done < file2.txt

##===================================================================##
##===================================================================##
##================ start to compare these two files =================##
##===================================================================##
##===================================================================##

for ((i=0; i<idx1; i++)); do
   for ((j=0; j<idx2; j++)); do

        DESC1="file1array$i[0]"
        DM1="file1array$i[1]"
        W1="file1array$i[2]"
        S1="file1array$i[3]"
        CRITICAL1="file1array$i[4]"
        GRADE1="file1array$i[5]"

        DESC2="file2array$j[0]"
        W2="file2array$j[1]"
        S2="file2array$j[2]"

        [ $i == 0 ] && LOSSarray+=(["$j"]="${!DESC2}")

        if [[ "${!GRADE1}" == [E-GT-Z][1-9] && "${!DESC1}" == "${!DESC2}" ]]; then

             W1_Judge=`expr "scale=3; ${!W1} - ${!W2}" | bc`
             S1_Judge=`expr "scale=3; ${!S1} - ${!S2}" | bc`

             [ $W1_Judge != 0 -o $S1_Judge != 0 ] && declare -A jgWS=( ["${!DESC1}"]="WSNG" )

        elif [[ "${!GRADE1}" == [E-GT-Z][1-9] && "$j" == `expr $idx2 - 1` ]]; then

             [[ -z $(echo "${LOSSarray[@]}" | grep -o "${!DESC1}") && "${!CRITICAL1}" != "NULL" ]] && declare -A jgLOSS=( ["${!DESC1}"]="LOSSNG" )

        elif [[ "${!GRADE1}" != [E-GT-Z][1-9] && "${!DESC1}" == "${!DESC2}" ]]; then

             [[ "${!DM1}" == [1-2]x* || "${!DM1}" == "X" ]] && declare -A jgEXTRA=( ["${!DESC1}"]="EXTRANG" )

        fi

    done


    if [[ "${jgWS[${!DESC1}]}" == "WSNG" ]]; then

    echo "${!DESC1}: ${ESC}[0;31mWidth or Space NG${ESC}[0m"

    elif [[ "${jgLOSS[${!DESC1}]}" == "LOSSNG" ]]; then

    echo "${!DESC1}: ${ESC}[0;31mLOSS NG${ESC}[0m"

    elif [[ "${jgEXTRA[${!DESC1}]}" == "EXTRANG" ]]; then

    echo "${!DESC1}: ${ESC}[0;31mEXTRA NG${ESC}[0m"

    else

    echo "${!DESC1}: OK"

    fi


done

It's ok to proceed whole script and output following result:

EEE: Width or Space NG
AAA: OK
C+C: OK
HHH: LOSS NG
III: EXTRA NG
JJJ: EXTRA NG
D+: OK

but if I change file1.txt like this(take the line with "D+" to line1):

D+ X 2 3 Y T1 
EEE 1x 9 6 Y E2 
AAA X 1 2 Y E2 
C+C X 8 1 Y T1 
HHH 1x 5 5 Y T2 
III X 5 5 Y S1 
JJJ X 5 5 Y S1 

I got following result:

D+: syntax error: operand expected (error token is "+")
  1. How can I solve this problem if I don't wanna edit file1.txt?

  2. How can I read the 1st column of file2.txt as a array that I don't need to do it in for-loop?

liltme
  • 91
  • 7
  • Please specify your input format, we can only guess which columns `GRADE1`, `DESC1` and `DM1` are based on your code which is tiresome. It's great that you are trying to explain the problem and even posted code, but your problem description is way too complicated and hard to read. – Adrian Frühwirth Mar 24 '14 at 10:39
  • Thanks for your advise, I modified my question a little bit – liltme Mar 25 '14 at 02:36

1 Answers1

3

The problem is that bash throws an error if you try to access an element of an undeclared array using a +. For example:

$ echo "${arr[D+]}"
-bash: D+: syntax error: operand expected (error token is "+")

$ echo "${arr[foo]}" # works

However, if you declare the array first, it works:

$ declare -A arr
$ echo ${arr[D+]} # works

So, you need to make sure that the arrays jgWS, jgLOSS and jgEXTRA have been declared up front, before you access them in your if-statements.

For example, currently the jgWS array is declared only if this condition is met: [ $W1_Judge != 0 -o $S1_Judge != 0 ]. Later on, you try to use the array here: if [[ "${jgWS[${!DESC1}]}" == "WSNG" ]], but it might not have been initialised, in which case it fails.

dogbane
  • 266,786
  • 75
  • 396
  • 414
  • 2
    Specifically, without a declaration, the array is an ordinary array, not an associative array, and the index of an ordinary array is evaluated in an arithmetic context, so the syntax error is the lack of a second operand for the addition operator. – chepner Mar 24 '14 at 12:38