1

Hereafter are two read statements, one that uses a space as a delimiter, and the other \0. Only the first works. What am I doing wrong with the second?

$ IFS=' '; read first second  < <(printf "%s " "x" "y" ); echo "$first+$second"

x+y

$ IFS=$'\0'; read first second  < <(printf "%s\0" "x" "y" ); echo "$first+$second"

xy+

Erwann
  • 677

1 Answers1

1

Try using an array, and the mapfile AKA readarray built-in. See help mapfile for details. If you provide an empty string as the argument to mapfile's -d option, it will use a NUL as the delimiter.

First, create a function that can join an array into a single string with an arbitrary separator:

$ joinarray() { local IFS="$1"; shift; echo "$*"; }

This uses the first argument as the output separator, then uses echo to print the remaining arguments as a single string. This isn't limited to joining arrays, it works with any arguments (arrays, scalar variables, fixed strings), but it's particularly useful when used with arrays. It's called joinarray so it doesn't conflict with the standard join command.

Then, using an array called "$array":

$ mapfile -d '' array < <(printf "%s\0" "x" "y" )   # read the data into $array

$ declare -p array # show that the data was read correctly declare -a array=([0]="x" [1]="y")

$ joinarray + "${array[@]}" # output the array joined by + characters x+y

cas
  • 78,579
  • Weird to declare an array after it has been read into. I'm going to withhold from accepting this answer should anyone wish to explain why the basic approach does not work. – Erwann Mar 06 '22 at 04:05
  • 1
    That declare -p statement is NOT declaring an array. declare -p prints an existing variable - it's only there to demonstrate that the data was correctly read into the array, See help declare. The array was created by the mapfile command. – cas Mar 06 '22 at 04:10
  • The "basic" approach doesn't work because bash has difficulty working with NUL characters. bash variables, for example, can't hold NUL characters because bash variables are standard NUL-terminated C strings. BTW, bash is not a good language for processing data, in fact it is terrible at that. But that's OK, processing data is NOT its job. bash's job is to co-ordinate the execution of other programs (e.g. awk, sed, perl, grep, cut, and many others) to process data. – cas Mar 06 '22 at 04:16
  • "bash is not a good language for processing data," This is just a warmup for writing a script that outputs two values, one of which may have spaces in it. Hence experimenting with various delimiters. I think I'm going to make that a parameter instead. – Erwann Mar 06 '22 at 04:24