1

$ cat /proc/asound/cards

 0 [MID            ]: HDA-Intel - HDA Intel MID
                      HDA Intel MID at 0xb0610000 irq 64
 1 [PCH            ]: HDA-Intel - HDA Intel PCH
                      HDA Intel PCH at 0xb0614000 irq 65

I am trying to save the second line of each entry into a BASH array:

eval sound_card_array=($(awk 'NR%2==0' /proc/asound/cards)) #also tried without eval -> same result

#echo $(awk 'NR%2==0' /proc/asound/cards) --> this produces the proper output of each line

which should look like this:

["HDA Intel MID at 0xb0610000 irq 64", "HDA Intel PCH at 0xb0614000 irq 65"]

Instead, when I print out sound_card_array, I get only parts of the strings, or I get them all in different array elements. I have tried putting quotes around the awk call, adding echo, putting quotes around the variable when I access the array (i.e. "${sound_card_array[$i]}"), but none work.

UPDATE: Thanks guys. Maybe my problem is also with the way I'm accessing the array:

for sc in "${!sound_card_array[@]}"
do
        if [ "$sc" -lt "$((${#sound_card_array[@]}-1))" ]; then
                j_pair $sc "${sound_card_array[$i]}"
        else
                j_pair_last $sc "${sound_card_array[$i]}"
        fi

done

where j_pair and j_pair_last are BASH functions I wrote which take two arguments and echo them to a file:

function j_pair {
        printTabs
        echo  "\"$1\":\"$2\","
}
function j_pair_last {
        printTabs
        echo  "\"$1\":\"$2\""
}

I'm new to BASH, so I'm sure there are many things I could be doing wrong. Thanks again for all the help!

For awk and printf:

$ arr=($(awk 'NR%2==0{$1=$1; print}' /proc/asound/cards))
$ printf "%s\n" "${arr[@]}"

HDA
Intel
MID
at
0xb0610000
irq
64
HDA
Intel
PCH
at
0xb0614000
irq
65

3 Answers 3

1

Just using Bash:

sound_card_array=() i=0
while IFS= read -r line; do
    (( i++ % 2 )) && sound_card_array+=("${line:22}")
done < /proc/asound/cards

Test:

sound_card_array=() i=0
while IFS= read -r line; do
    (( i++ % 2 )) && sound_card_array+=("${line:22}")
done < sample.txt
printf '%s\n' "${sound_card_array[@]}"

Output:

HDA Intel MID at 0xb0610000 irq 64
HDA Intel PCH at 0xb0614000 irq 65
Sign up to request clarification or add additional context in comments.

3 Comments

All BASH! Probably even better. Every time I searched for how to read only the second line of a file, people always showed awk solutions. However, when I iterate through the array with 'for sc in "${!sound_card_array[@]}" ' I get an empty element at the end.
@MrUser Test shows well. Any different thing you might have made? Perhaps update your question with it?
You're right! It did work. After anubhava helped me see that I was using the wrong iterator in my for loop ($i instead of $sc because I was looking at examples that used $i and forgot to update...gulp), and after you updated your code with the (( i++ % 2 )), it all works. Awesome. Thanks.
1

I can see 2 options :

If the number of word is constant :

sound_card_array=($(awk 'NR%2==0' cards ))

echo ${sound_card_array[@]:0:7}
HDA Intel MID at 0xb0610000 irq 64

echo ${sound_card_array[@]:7:7}
HDA Intel PCH at 0xb0614000 irq 65

Or :

sound_card_array=($(awk 'NR%2==0{$1=$1;a=$0; gsub(" +","_",a); print a}' cards ))

echo ${sound_card_array[0]} | tr "_" " "
HDA Intel MID at 0xb0610000 irq 64

echo ${sound_card_array[1]} | tr "_" " "
HDA Intel PCH at 0xb0614000 irq 65

Hope this helps

Comments

1

Problem is in your use of eval.

You don't need to (and must not) use eval to create an array from awk's output in BASH. Use IFS while assigning it to an array:

IFS=$'\n' arr=($(awk 'NR%2==0{$1=$1; print}' /proc/asound/cards))

PS: I used $1=$1 to make awk reformat and strip out all leading space in 2nd line.

Then to test:

printf "%s\n" "${arr[@]}"
HDA Intel MID at 0xb0610000 irq 64
HDA Intel PCH at 0xb0614000 irq 65

9 Comments

I didn't know that $1=$1 would strip out all the leading spaces! I was using gsub, and very awkwardly I might add. However, this still didn't work for me. Maybe it's because of the way I'm accessing the elements. (see my update above)
What do you get when you use printf "%s\n" "${arr[@]}" command?
I looked at your script and looks like for sc in "${!sound_card_array[@]}" is the problem. You need to use: for sc in "${sound_card_array[@]}" here
But wouldn't that give me the value, and not the index? If I do that, then sc is the string itself and I can't print out the array iterator value. I access the value by using ${sound_card_array[$sc]}, but you did show me that I was using $i instead of $sc! Oops.
Great to know. IMO this is much safer than using substring of 22 chars later. What if you get an input with variable # of spaces some day. For striping leading spaces in BASH use: shopt -s extglob; echo "${line##+([[:blank:]])}"
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.