4

Let say, have a command genpairs which generates null-terminated strings.

key1 \0 val1 \0 key2 \0 val2 \0

Want read the above input into bash variables in pairs. The following not works for me:

genpairs() { #for the demo
    printf "%d\0x\0" 1
    printf "%d\0y\0" 2
    printf "%d\0z\0" 3
}
#the above generates 1  \0   x  \0   2  \0   y  \0   3  \0   z  \0 etc...
while IFS= read -r -d '' key val; do
        echo "key:[$key] val:[$val]"
done < <(genpairs)

prints

key:[1] val:[]
key:[x] val:[]
key:[2] val:[]
key:[y] val:[]
key:[3] val:[]
key:[z] val:[]

e.g. the read somewhat doesn't split on the $'\0' into two variables.

The wanted output:

key:[1] val:[x]
key:[2] val:[y]
key:[3] val:[z]

How to read null-terminated input into multiple variables?

EDITED the OP's question - added a better demo - x y z

I can solve it as:

n=0
while IFS= read -r -d '' inp; do
        if (( n % 2 ))
        then
                val="$inp"
                echo "key:[$key] val:[$val]"
        else
                key="$inp"
        fi
        let n++
done < <(genpairs)

This prints the

key:[1] val:[x]
key:[2] val:[y]
key:[3] val:[z]

but it looks to me really terrible solution...

1 Answer 1

5

Just use two read statements:

while IFS= read -r -d '' key && IFS= read -r -d '' val; do
    echo "key:[$key] val:[$val]"
done < <(genpairs)

Using Bash≥4.4, you can also use mapfile with its -d switch:

while mapfile -n 2 -d '' ary && ((${#ary[@]}>=2)); do
    echo "key:[${ary[0]}] val:[${ary[1]}]"
done < <(genpairs)
Sign up to request clarification or add additional context in comments.

1 Comment

WHY I need ask for such simple solutions... :( Feels stupid. Thanx a lot!!!

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.