Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am trying to store values of the first line of a text file into an array. Here is what I have so far:

arr_values=()

awk '
    NR==1 {
            for (i=0; i<=NF; i++)
               'arr_values[i]'=$i            #error here
          }' file.txt

for ((i=0; i<${#arr_values[@]}; i++))
do
   echo ${arr_values[i]}
done

I am getting an error with initializing the array mainly because I don't know how to use awk to initialize an external array. Any suggestions (only with awk)? Thanks.

Apologize for the cross post, I didn't get the answer I wanted.

share|improve this question
1  
GNU awk? mawk? You should specify it. There are literally at least a dozen flavors that differ in subtle ways. –  0xC0000022L Jun 23 at 16:10

4 Answers 4

You might get better answers if you explained the context as to why awk... and what the first line of data looks like.

Since you haven't changed the field separator, I'm assuming that you are processing a line of items separated by spaces. The following will do exactly what you are looking for:

arr_values=()

read -ra arr_values <<< $(head -n 1 file.txt)

for s in "${arr_values[@]}"; do
    echo "$s"
done

All the work is done in the read command. Unless you have a need to process the values in an array multiple times; then, you could simply do:

set -f    # disable globbing, in case the lines contain wildcard characters
for s in $(head -n 1 file.txt); do
    set +f
    echo "$s"
done
set +f

This will put each non-blank field entry that is separated by blanks into $s and make one pass through the loop.

share|improve this answer

You can't do it precisely this way. You have to let the awk command execute, creating a series of output values delimited by some delimiter (space, tab, NUL or something), then assign these to the array elements. The reason for this is that awk is a program that is run by the shell and it runs to completion before any more shell operations execute. You can't embed shell stuff in your awk stuff like this.

You can do something like the below to use your simple example, but I'm not certain the awk code you supplied will do what you want in any case. If a file has zero records or more than one record, the output (and, thus, the shell array) will contain the lines of the file. It looks like you want to have the output array contain a set of integers from zero to the number of fields you find in a file if-and-only-if it contains only one record. If you wish to avoid having larger files show up in the array, you will have to add a second patternless action in the awk code containing only "{ }" as the action as I have done below. Also, turn off filename wildcard expansion (set -f) in case the line contains wildcard characters \[*?.

set -f
arr_values=(`awk '
    NR==1 {
            for (i=0; i<=NF; i++)
               print $i
          }

          { }' file.txt`)
set +f
for ((i=0; i<${#arr_values[@]}; i++))
do
   echo "${arr_values[i]}"
done
share|improve this answer

If you want to use awk, you can do like this:

arr_values=( $(awk '{print;exit}' file) )

The shell will do the splitting on whitespace. Note that if the line contains wildcards, they will be expanded to the list of matching files (if there are any). Use set -f to disable wildcard expansion.

set -f
arr_values=( $(awk '{print;exit}' file) )
set +f
share|improve this answer
    
Why not BEGIN? Did you consider the difference between FNR and NR also ... especially when the AWK script is told to process several input files?! –  0xC0000022L Jun 23 at 16:09
    
@0xC0000022L: Why BEGIN? In BEGIN, no record is read. And the OP seem only process one file. –  cuonglm Jun 23 at 16:14
    
then FNR is still the better option, unless this is a prototype. But as we all know prototypes tend to end up in production down the line. –  0xC0000022L Jun 23 at 17:19
    
@0xC0000022L: Agree. In this case, I use NR because it still right and shorter than FNR :) –  cuonglm Jun 23 at 17:48

I don't know about the other stuff, but if you're splitting on white-space, this will the store the first line of a text file in the shell array split on white space:

set -f ; set -- $(head -n1 <textfile) ; set +f

That's all it takes. Now your positional parameters are the various array indices and your array is "$@".

share|improve this answer
    
Its not what I'm looking for but thanks for the taking the time to answer my question –  Alias Jun 23 at 16:01
2  
You can set the bash arrays in the same way, and you can change how they split with IFS=${split}. –  mikeserv Jun 23 at 16:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.