Arnaud F.
Arnaud F.

Reputation: 8452

Assign ksh/bash array with awk

I'm trying to transform a given line to an array, for example this line :

My first\t \tHello world

to the following ksh/bash array:

[0]="My first"
[1]=""
[2]="Hello world"

My code:

TAB=`printf '\011'`

query()
{
    echo "$1"|awk -F"$TAB" '
        { 
            for(i = 0; i < NF; i++)
                QueryArray[i]=$i
        }';
}

line=`head -n 1 myFile`
typeset -a QueryArray;
query "$line"
echo "Array length: ${#QueryArray[*]}"
echo "- " ${QueryArray[0]}
echo "- " ${QueryArray[1]}
echo "- " ${QueryArray[2]}

but doesn't work, any suggestions?

Thanks.

Upvotes: 1

Views: 1631

Answers (3)

glenn jackman
glenn jackman

Reputation: 247012

I have an older ksh that does not understand $'ANSI' strings, so:

str2array () {
    typeset arrayname=$1
    typeset IFS=$2
    shift 2
    eval "set -A $arrayname \$*"
}

s="Hello        World"     # tabs entered literally with "Ctrl-V tab"
str2array myarray " " "$s"     # another literal tab as 2nd parm
typeset -i i=0
while [[ $i -lt ${#myarray[@]} ]]; do
    printf "%d\t%s\n" $i "${myarray[$i]}"
    i=$(( i+1 ))
done

for bash:

str2array () {
    local arrayname=$1
    local IFS=$2
    shift 2
    eval "$arrayname=( \$* )"
}

s=$'hello\t\tworld'
str2array myarray $'\t' "$s"
for (( i=0; i < ${#myarray[@]}; i++ )); do
    printf "%d\t%s\n" $i "${myarray[$i]}"
done

I'm getting the same result ar Arnaud's comment to David: with "word\t\tword", the middle field is being dropped. I don't see that with a different delimiter such as colon.

ksh

Blank Interpretation
After parameter and command substitution, the results of substitutions are scanned for the field separator characters (those found in IFS) and split into distinct arguments where such characters are found. Explicit null arguments ( "" ) or ('') are retained. Implicit null arguments (those resulting from parameters that have no values) are removed.

bash

Word Splitting
... The shell treats each character of IFS as a delimiter, and splits the results of the other expansions into words on these characters. If IFS is unset, or its value is exactly <space><tab><newline>, the default, then sequences of <space>, <tab>, and <newline> at the beginning and end of the results of the previous expansions are ignored, and any sequence of IFS characters not at the beginning or end serves to delimit words. If IFS has a value other than the default, then sequences of the whitespace characters space and tab are ignored at the beginning and end of the word, as long as the whitespace character is in the value of IFS (an IFS whitespace character). Any character in IFS that is not IFS whitespace, along with any adjacent IFS whitespace characters, delimits a field. A sequence of IFS whitespace characters is also treated as a delimiter. If the value of IFS is null, no word splitting occurs.

Upvotes: 1

David W.
David W.

Reputation: 107080

Doesn't work in KSH.

You need to use typeset instead of declare, and use the function keyword. Otherwise, satyajit's answer works just fine.

Kornshellified for you...

function query
{
    IFS=$'\t'
    ind=0
    for i in $1
    do
        QueryArray[$ind]=$i
        let "ind+=1"
    done
    unset IFS

}

typeset -a QueryArray #Actually this is optional in Kornshell
query "Hello                World" #Hello\t \tWorld

# What the heck? Might as well go all Korn: print vs. echo
print "Array length: ${#QueryArray[*]}"
print -- "- ${QueryArray[0]}"
print -- "- ${QueryArray[1]}"
print -- "- ${QueryArray[2]}"

Upvotes: 1

Satyajit
Satyajit

Reputation: 3859

query()
{
    IFS=$'\t'
    ind=0       
    for i in $1 
        do 
          QueryArray[$ind]=$i 
          let "ind+=1" 
        done
    unset IFS

}

declare -A QueryArray;
query "Hello        World" #Hello\t \tWorld
echo "Array length: ${#QueryArray[*]}"
echo "- " ${QueryArray[0]}
echo "- " ${QueryArray[1]}
echo "- " ${QueryArray[2]}

Upvotes: 1

Related Questions