1

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.

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Seems to be I'm blocked, will accept your answer, thanks for reply !
1
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]}

Comments

1

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]}"

1 Comment

It works only if you have a character between 2 \t\t, if you have Hello\t\tWorld, it will only return an array length of 2 and not 3 as I expect

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.