简体   繁体   中英

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.

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

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM