Linux bash array in array

Array of arrays in bash

I’m attempting to read an input file line by line which contains fields delimited by periods. I want to put them into an array of arrays so I can loop through them later on. The input appears to be ok, but ‘pushing’ that onto the array (inData) doesn’t appear to be working. The code goes :

Input file: GSDB.GOSALESDW_DIST_INVENTORY_FACT.MONTH_KEY GSDB.GOSALESDW_DIST_INVENTORY_FACT.ORGANIZATION_KEY infile=$ OIFS=$IFS IFS=":" cat $ | while read line do line=$ inarray=($) # echo $ # echo $ # echo $ # echo $ # echo $ inData=("$" "$") done IFS=$OIFS echo $ for ((i = 0; i < $; i++)) do echo $i for ((j = 0; j < $; j++)) do echo $ done done 

Instead of cat $ | while read line . done, use while read line . done < $Explanation: the pipe you use creates a sub shell to run the while loop. Now this child process has it's own copy of the environment and can't pass any variables back to its parent (as in any unix process). See Bash variable scope

7 Answers 7

Field nest box in bash but it can not circumvent see the example.

#!/bin/bash # requires bash 4 or later; on macOS, /bin/bash is version 3.x, # so need to install bash 4 or 5 using e.g. https://brew.sh declare -a pages pages[0]='domain.de;de;https' pages[1]='domain.fr;fr;http' for page in "$" do # turn e.g. 'domain.de;de;https' into # array ['domain.de', 'de', 'https'] IFS=";" read -r -a arr " site="$" lang="$" prot="$" echo "site : $" echo "lang : $" echo "prot : $" echo done 

I dont understand, for me it works only for the very first item in the main array and not for the next rows. Any idea why that might be ?

Using spaces in this case is even simpler: pages[0]="domain.de de https" easily translates into an indexed array with arr=($) .

Bash has no support for multidimensional arrays. Try

array=(a b c d) echo $ echo $ echo $

For tricks how to simulate them, see Advanced Bash Scripting Guide.

thanks, i decided to process each record as I read them from the file, prveting the need for the additional array.

Knowing that you can split string into "array". You could creat a list of lists. Like for example a list of databases in DB servers.

dbServersList=('db001:app001,app002,app003' 'db002:app004,app005' 'dbcentral:central') # Loop over DB servers for someDbServer in $ do # delete previous array/list (this is crucial!) unset dbNamesList # split sub-list if available if [[ $someDbServer == *":"* ]] then # split server name from sub-list tmpServerArray=($) someDbServer=$ dbNamesList=$ # make array from simple string dbNamesList=($) fi # Info echo -e "\n----\n$someDbServer\n--" # Loop over databases for someDB in $ do echo $someDB done done 
---- db001 -- app001 app002 app003 ---- db002 -- app004 app005 ---- dbcentral -- central 

I struggled with this but found an uncomfortable compromise. In general, when faced with a problem whose solution involves using data structures in Bash, you should switch to another language like Python. Ignoring that advice and moving right along:

My use cases usually involve lists of lists (or arrays of arrays) and looping over them. You usually don't want to nest much deeper than that. Also, most of the arrays are strings that may or may not contain spaces, but usually don't contain special characters. This allows me to use not-to-confusing syntax to express the outer array and then use normal bash processing on the strings to get a second list or array. You will need to pay attention to your IFS delimiter, obvi.

Читайте также:  Mac mini 2012 linux

Thus, associative arrays can give me a way to create a list of lists like:

declare -A JOB_LIST=( [job1] = "a set of arguments" [job2] = "another different list" . ) 

This allows you to iterate over both arrays like:

for job in "$"; do /bin/jobrun $ done 

Ah, except that the output of the keys list (using the magical $ <. >) means that you will not traverse your list in order. Therefore, one more necessary hack is to sort the order of the keys, if that is important to you. The sort order is up to you; I find it convenient to use alphanumerical sorting and resorting to aajob1 bbjob3 ccjob6 is perfectly acceptable.

declare -A JOB_LIST=( [aajob1] = "a set of arguments" [bbjob2] = "another different list" . ) sorted=($(printf '%s\n' "$"| /bin/sort)) for job in "$"; do for args in "$"; do echo "Do something with $ in $" done done 

A bash array of arrays is possible, if you convert and store each array as a string using declare -p (see my function stringify). This will properly handle spaces and any other problem characters in your arrays. When you extract an array, use function unstringify to rebuild the array. This script demonstrates an array of arrays:

#!/bin/bash # BASH array of arrays demo # Convert an array to a string that can be used to reform # the array as a new variable. This allows functions to # return arrays as strings. Works for arrays and associative # arrays. Spaces and odd characters are all handled by bash # declare. # Usage: stringify variableName # variableName - Name of the array variable e.g. "myArray", # NOT the array contents. # Returns (prints) the stringified version of the array. # Examples. Use declare to make an array: # declare -a myArray=( "O'Neal, Dan" "Kim, Mary Ann" ) # (Or to make a local variable replace declare with local.) # Stringify myArray: # stringifiedArray="$(stringify myArray)" # Reform the array with any name like reformedArray: # eval "$(unstringify reformedArray "$stringifiedArray")" # To stringify an argument list "$@", first create the array # with a name: declare -a myArgs=( "$@" ) stringify() < declare -p $1 ># Reform an array from a stringified array. Actually this prints # the declare command to form the new array. You need to call # eval with the result to make the array. # Usage: eval "$(unstringify newArrayName stringifiedArray [local])" # Adding the optional "local" will create a local variable # (uses local instead of declare). # Example to make array variable named reformedArray from # stringifiedArray: # eval "$(unstringify reformedArray "$stringifiedArray")" unstringify() < local cmd="declare" [ -n "$3" ] && cmd="$3" # This RE pattern extracts 2 things: # 1: the array type, should be "-a" or "-A" # 2: stringified contents of the array # and skips "declare" and the original variable name. local declareRE='^declare ([^ ]+) [^=]+=(.*)$' if [[ "$2" =~ $declareRE ]] then printf '%s %s %s=%s\n' "$cmd" "$" "$1" "$" else echo "*** unstringify failed, invalid stringified array:" 1>&2 printf '%s\n' "$2" 1>&2 return 1 fi > # array of arrays demo declare -a array # the array holding the arrays declare -a row1=( "this is" "row 1" ) declare -a row2=( "row 2" "has problem chars" '!@#$%^*(*()-_=+["|\:;,.?/' ) declare -a row3=( "$@" ) # row3 is the arguments to the script # Fill the array with each row converted to a string. # stringify needs the NAME OF THE VARIABLE, not the variable itself array[0]="$(stringify row1)" array[1]="$(stringify row2)" array[2]="$(stringify row3)" # Print array contents for row in "$" do echo "Expanding stringified row: $row" # Reform the row as the array thisRow eval "$(unstringify thisRow "$row")" echo "Row values:" for val in "$" do echo " '$val'" done done 

Источник

Читайте также:  Можно ли linux поставить поверх windows

How to Simulate an Array of Arrays in Bash

Bash is indeed an interpreted, interactive language, and how much space to reserve in advance does not have to be known. It is also possible to make ready a new array dynamically without declaring it or extending a previously defined array to include further entries. Still, multidimensional arrays aren’t supported by bash, and we can’t get array components that are also arrays. Fortunately, multidimensional arrays can be simulated. This article will provide some illustrations of the simulation of an array of arrays in a bash script.

Example 01: Using Simple “For” Loops

We have an example of simulating an array of arrays using the simple method. Let’s start demonstrating how to load a user-defined m x n table with random numbers (that aren’t random, because each column will at all times have a similar number in each run on most of its rows, but that does not apply to the question), and print it. When we work on either a bash that you do have, bash version 4, the below script would certainly work efficiently. We should not solitary declare 0; that is more like a perfect solution to values being accepted vigorously. We have declared an array with the “-A” keyword. If we don’t define the associative array using -A, the code may not work for us. The read keyword is then used to read the user’s input, which is rows and columns of a table. Then we have used two “for” loops for the incrementation of rows and columns of a table. In for loop, we have been making a two-dimensional array. In the next for loop, all the values of an array have been displayed.

When you run the bash file, it will ask a user to enter rows and columns as “m” and “n”. After that, for loops will generate a two-dimensional table as below.

Example 02: Using Hashes

Taking the same instance, we can emulate the arrays using hashes. However, we have to be more careful about leading zeros and several other stuff. The next explanation is working. However, the way out is very far from ideal. We have been taking rows and columns manually. For loop is used to make a matrix. Then we have been using hashes to emulate the two-dimensional array. At last, the array will be printed out as below.

Execute the file “input.sh” in the bash shell using the bash command. You will find a table with rows and columns number mentioned.

Example 03: Using Associative Arrays

Let’s have an example of simulation having a somewhat similar effect using the associative arrays used as an array of arrays as below. After the declaration of the associative array, we have defined values for arrays separately. After that, we have made it to print out the values in two dimensional way.

Читайте также:  Virtualbox установка linux на флешку

You can see the output as a two-dimensional array while running the file. If we ignore the “declare -A arr” line, the echo statement may display (2 3) rather than (0 1), since (0,0), (1,0), and others may have been used as a mathematical expression and calculated to 0 (the value at the right side of a comma).

Example 04: Using Name-references

In bash, it is a frequent issue with referencing arrays inside arrays that you’ll have to construct name-references using declare -n. That name afterward -n serves as a name ref for the value allocated (after =). Currently, we handle this variable only with attribute name ref to extend as though it was an array and extend the appropriately cited array as beforehand. Let’s have an example of name refs. We have successfully declared two arrays. After that, we have assigned both the arrays to another array as a member. We have used for loop to make a two-dimensional array. We have made another variable to add the one-by-one values of the array “group” into it for comparison. Deep down, it will go to members of inner arrays “bar” and “foo” to take values and compare them while printing the message.

When we execute the file “input.sh”, you will see the below output. The variable “lst” has values of inner arrays within the array “groups”.

Example 05: Using Cut Keyword

Only now, I’ve stumbled into it. There had been a fairly straightforward approach that worked for everyone. To show a main map for the system, I decided to use an array containing a device name and a screen location. We have to concatenate the title of the unit and the corresponding location of a display into some single string, using only a delimiter, which we assumed will not occur in either of our values (in my case, I used .). And I used a “cut” keyword to split the concrete values into their components if necessary. There may be a clearer and easier approach to do it, though, and this is only to illustrate that in a sense, in bash, we can build a multidimensional array, although it does not help it. After that, you have to print both the device name and its location separately after creating the substring.

Let’s run the bash “input.sh” file. You will see the separated device and its location in the shell prompt as while execution. The solution works using the cut command.

Example 06

Let’s take a little longer example to emulate a multidimensional array. In the load_alpha() function, all the alphabets will be loaded into the array. After that, the print_Alpha() function is declared and used to print out all the alphabets in the row-major order as a matrix or two-dimensional format. On the other hand, we have been using the rotate() function to rotate the array. Let’s try this example in the bash shell to see results.

While execution, we have found a very beautiful structure of multidimensional array in the bash shell as below

Conclusion

We have successfully tried some examples for simulating arrays of arrays in bash. I hope it works!

About the author

Aqsa Yasin

I am a self-motivated information technology professional with a passion for writing. I am a technical writer and love to write for all Linux flavors and Windows.

Источник

Оцените статью
Adblock
detector