How to read null-terminated lines in pairs using bash

Let's say we get a command genpairsthat generates lines ending with zero.

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

Want to read the above input to bash variables in pairs. The following does not work 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:[]

eg. the read is not split $'\0'into two variables.

Required Conclusion:

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

How to read zero-terminated input in multiple variables?

EDIT question OP - added more efficient demo version

I can solve this 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)

Sends

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

but it looks like a really scary decision for me ...

+4
source share
1 answer

Just use two operators read:

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

Bash ≥4.4, mapfile -d:

while mapfile -n 2 -d '' ary && ((${#ary[@]}>=2)); do
    echo "key:[${ary[0]}] val:[${ary[1]}]"
done < <(genpairs)
+5

Source: https://habr.com/ru/post/1674411/


All Articles