Awk: What is the difference between: X[a,b,c] - X[a][b,c] - X[a][b][c]


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Awk: What is the difference between: X[a,b,c] - X[a][b,c] - X[a][b][c]
# 1  
Old 08-05-2017
Wrench Awk: What is the difference between: X[a,b,c] - X[a][b,c] - X[a][b][c]

I have awk appearing to behave inconsistently. With the same variable it will give the message:

Code:
fatal: attempt to use array `X["2"]' in a scalar context

and, if I try to correct that, then:

Code:
fatal: attempt to use a scalar value as array

I'm using a three dimensional array. There seems to be a significant difference to how awk - GNU Awk 4.1.4, API: 1.1 (GNU MPFR 3.1.5, GNU MP 6.1.2) - treats the following:

Code:
X[a,b,c]
X[a][b,c]
X[a][b][c]

What is the difference between these? Where can I find it documented?

To demonstrate, with a small piece of code:

Code:
BEGIN {
        X[1,"Jim","The quick brown fox jumps over the lazy dogs"]++;
        Y[1]["Jim","The quick brown fox jumps over the lazy dogs"]++;
        Z[1]["Jim"]["The quick brown fox jumps over the lazy dogs"]++;
        X[2,"Jack","The quick brown foxs jumps over the lazy dogs"]++;
        Y[2]["Jack","The quick brown foxs jumps over the lazy dogs"]++;
        Z[2]["Jack"]["The quick brown foxs jumps over the lazy dogs"]++;
        X[3,"Joe","The quick brown foxs jumps over the lazy dogs"]++;
        Y[3]["Joe","The quick brown foxs jumps over the lazy dogs"]++;
        Z[3]["Joe"]["The quick brown foxs jumps over the lazy dogs"]++;
      }
END {
for ( x in X )
        print x;
for ( y in Y )
        print y;
for ( z in Z )
        {
        for ( a in Z[z] )
                print z " : " a  # -> gives the error 'awk: demo.awk:20: fatal: attempt to use array `Z["1"]["Jim"]' in a scalar context' ":" Z[z][a];
        }
}

$ awk -f demo.awk </dev/null

Code:
1JimThe quick brown fox jumps over the lazy dogs
2JackThe quick brown foxs jumps over the lazy dogs
3JoeThe quick brown foxs jumps over the lazy dogs
1
2
3
1 : Jim
2 : Jack
3 : Joe

As the code says, in the last example, if I try
Code:
Z[z][a]

which seems the correct syntax, it gives the error
Code:
fatal: attempt to use array `Z["1"]["Jim"]' in a scalar context

.

Code:
split(Y[1],y_bits,SUBSEP);

gives:
Code:
awk: demo.awk:14: fatal: attempt to use array `Y["1"]' in a scalar context

The same error occurs for
Code:
split(Z[1],z_bits,SUBSEP);

but
Code:
split(X[1],x_bits,SUBSEP);

works.
# 2  
Old 08-05-2017
Welcome to the forum.

None of the awk version I know provides the array constructs you present as the second and third version. man awk:
Quote:
Awk provides one-dimensional arrays.
So - I'm surprised you don't get a error msg like I do for your script:
Code:
awk: line 4: syntax error at or near [

# 3  
Old 08-05-2017
Network

Awk, in this case, particularly, gawk, has supported multidimensional arrays for a long time. On linux, 'awk' is usually 'gawk', so the distinction isn't important.

You can see one manual entry here:

Code:
https://www.gnu.org/software/gawk/manual/html_node/Arrays-of-Arrays.html

It seems there are two mechanisms. In the case of:

Code:
X[a,b]

awk (gawk) it uses a separator character, known as 'SUBSEP'. So you can get 'a' and 'b' above by:
Code:
split(X,x_bits,SUBSEP);

gawk also provides 'true' arrays. What I'm trying to understand is the difference between these. The manual page is:

Code:
   Arrays
       Arrays  are  subscripted  with an expression between square brackets ([ and ]).  If the expression is an expression list (expr, expr ...)  then the array subscript is a string con‐
       sisting of the concatenation of the (string) value of each expression, separated by the value of the SUBSEP variable.  This  facility  is  used  to  simulate  multiply  dimensioned
       arrays.  For example:

              i = "A"; j = "B"; k = "C"
              x[i, j, k] = "hello, world\n"

       assigns the string "hello, world\n" to the element of the array x which is indexed by the string "A\034B\034C".  All arrays in AWK are associative, i.e., indexed by string values.

       The special operator in may be used to test if an array has an index consisting of a particular value:

              if (val in array)
                   print array[val]

       If the array has multiple subscripts, use (i, j) in array.

       The in construct may also be used in a for loop to iterate over all the elements of an array.  However, the (i, j) in array construct only works in tests, not in for loops.

       An  element  may be deleted from an array using the delete statement.  The delete statement may also be used to delete the entire contents of an array, just by specifying the array
       name without a subscript.

       gawk supports true multidimensional arrays. It does not require that such arrays be ``rectangular'' as in C or C++.  For example:

              a[1] = 5
              a[2][1] = 6
              a[2][2] = 7

       NOTE: You may need to tell gawk that an array element is really a subarray in order to use it where gawk expects an array (such as in the second argument to split()).  You  can  do
       this by creating an element in the subarray and then deleting it with the delete statement.

The version is:

Code:
$ awk -V
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 3.1.5, GNU MP 6.1.2)

---------- Post updated at 01:37 PM ---------- Previous update was at 01:06 PM ----------

OK, I think I've worked out the answer.

The two types of array are entirely different and incompatible. You cannot use split if you define the array as X[a][b][c].

It does allow you to mix the two types, as in X[a][b,c], as I did, but it is a really bad idea to do this as it seems to confuse the interpreter - this was my problem.

Here is some working code that sets up, then lists, the elements in the three dimensional array correctly - no use of split and it's OK.

Code:
BEGIN {
        Z[1]["Jim"]["The quick brown fox jumps over the lazy dogs"]=42;
        Z[1]["Harry"]["Colorless green ideas sleep furiously"]=41;
        Z[2]["Jack"]["The quick brown foxes jumps over the lazy dogs"]=40;
        Z[2]["Harry"]["Colorless green ideas sleep furiously"]=39;
        Z[3]["Joe"]["The quick brown foxes jumps over the lazy dog"]=38;
        Z[4]["James"]["The quick brown fox jumps over a lazy dog"]=37;
        Z[5]["Jimmy"]["The quick brown fox jumps over the lazy dog again"]=36;
      }
END {
print "Z[a,b,c]";
for ( a in Z )
        for ( b in Z[a] )
                for ( c in Z[a][b] )
                        print "a of Z[a]: " a "\t| b of Z[a][b] :\t" b  "\t| c of Z[a][b][c]:\t" c " |\t\tvalue of Z[a][b][c]:\t" Z[a][b][c];
}

Output:

Code:
$ awk -f demo.awk </dev/null
Z[a,b,c]
a of Z[a]: 1	| b of Z[a][b] :	Harry	| c of Z[a][b][c]:	Colorless green ideas sleep furiously |		value of Z[a][b][c]:	41
a of Z[a]: 1	| b of Z[a][b] :	Jim	| c of Z[a][b][c]:	The quick brown fox jumps over the lazy dogs |		value of Z[a][b][c]:	42
a of Z[a]: 2	| b of Z[a][b] :	Harry	| c of Z[a][b][c]:	Colorless green ideas sleep furiously |		value of Z[a][b][c]:	39
a of Z[a]: 2	| b of Z[a][b] :	Jack	| c of Z[a][b][c]:	The quick brown foxes jumps over the lazy dogs |		value of Z[a][b][c]:	40
a of Z[a]: 3	| b of Z[a][b] :	Joe	| c of Z[a][b][c]:	The quick brown foxes jumps over the lazy dog |		value of Z[a][b][c]:	38
a of Z[a]: 4	| b of Z[a][b] :	James	| c of Z[a][b][c]:	The quick brown fox jumps over a lazy dog |		value of Z[a][b][c]:	37
a of Z[a]: 5	| b of Z[a][b] :	Jimmy	| c of Z[a][b][c]:	The quick brown fox jumps over the lazy dog again |		value of Z[a][b][c]:	36

This User Gave Thanks to Fustbariclation For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. UNIX for Beginners Questions & Answers

awk to capture memory difference

Hi, I have a file which consists of the following information in repeating blocks. ************First iteration*************** xr_lab#show memory compare start Thu Sep 19 14:38:06.400 WIB <<<<<<<<<< START TIME Successfully stored memory snapshot in... (3 Replies)
Discussion started by: sand1234
3 Replies

2. Shell Programming and Scripting

awk to calculate difference of split and sum the difference

In the awk I am trying to subtract the difference $3-$2 of each matching $4 before the first _ (underscore) and print that value in $13. I think the awk will do that, but added comments. What I am not sure off is how to add a line or lines that will add sum each matching $13 value and put it in... (2 Replies)
Discussion started by: cmccabe
2 Replies

3. Shell Programming and Scripting

Difference in awk output and while

so, im going over one of my scripts and trying to optimize it. i have a code like this: cksum sjreas.py | awk '{prinnt $1$2}' This does what I need. However, i dont want to call the external command awk. so im doing this: cksum sjreas.py | while OFS=' ' read v1 v2 ; do printf... (4 Replies)
Discussion started by: SkySmart
4 Replies

4. UNIX for Dummies Questions & Answers

What is the difference in this two awk command?

What is the difference in these two awk command? Both returns same output but I am not sure what is the use of +0 in command 1. awk -F "," '{print $1+0,$2+0,$3+0}' awk -F "," '{print $1, $2, $3}' (3 Replies)
Discussion started by: later_troy
3 Replies

5. UNIX for Dummies Questions & Answers

Shell script - getting Time difference using awk

Hi..I have the data in a file like in this format, and I need the output time difference in seconds by using awk command. Start date/time and end date/time given in column 2,3 & 4,5. Please assist how to write shell script. File1.txt JOB1 10/09/2013 17:42:16 10/09/2013 17:43:46 SU 6202685/1... (4 Replies)
Discussion started by: mprithvi
4 Replies

6. Shell Programming and Scripting

awk -- telling the difference between strings and integers

This should be a really easy question. My input file will have a few fields that are strings in the first line, which I will extract and save as variables. The rest of the fields on every line will be integers and floating point numbers. Can awk tell the difference somehow? That is, is there... (5 Replies)
Discussion started by: Parrakarry
5 Replies

7. Shell Programming and Scripting

[Solved] awk Column difference

Hi, I've got what is probably quite an easy little (presumably) awk problem that I just can't seem to work out (mental block...I've already spent ages getting the data into this format!). I want to work out the difference between rows for certain columns. for example: 1359142876 RED 14... (3 Replies)
Discussion started by: chrissycc
3 Replies

8. Shell Programming and Scripting

AWK Script and Commandline difference

Hey there, I just stumbled upon a difference between using awk on the commandline and using it in a shellscript. I have a variable, e.g.: PROG=vim then i want to check if the package with this name is installed: TEMPVAL=$(dpkg -l | awk '{ if ($2 == "$PROG") print $2 }') (Im using... (10 Replies)
Discussion started by: MrSnail
10 Replies

9. Shell Programming and Scripting

AWK - Difference in multiple files

Hello again, I've run into another problem that I've been unable to solve. With everyone's help last time, the script worked perfectly! This problem takes a little more finesse, and the bash script I thought up didn't work, so I've canned it. I'd like to try awk if possible. Here's my... (6 Replies)
Discussion started by: Eblue562
6 Replies

10. UNIX for Dummies Questions & Answers

awk help in calulating difference for last two lines

Hi all, I have a requirement for a script to find out the increase in memory. We have a log native_stderr.log where this will log. bash-2.05$ tail -40 native_stderr.log | grep ': freed' <GC(4140): freed 168190456 bytes, 66% free (180990488/271776256), in 253 ms> <GC(4141): freed... (4 Replies)
Discussion started by: senthilkumar_ak
4 Replies
Login or Register to Ask a Question