[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-bash] How to set IFS temporarily? (along with assignment and a
From: |
Peng Yu |
Subject: |
Re: [Help-bash] How to set IFS temporarily? (along with assignment and array initiation) |
Date: |
Mon, 16 Mar 2015 11:49:46 -0500 |
On Mon, Mar 16, 2015 at 10:35 AM, Greg Wooledge <address@hidden> wrote:
> On Mon, Mar 16, 2015 at 09:40:54AM -0500, Peng Yu wrote:
>> I use the following 4 lines to set IFS temporarily. But it uses a
>> temporary variable OLD_IFS, which could be used by other accidentally.
>> Therefore, this piece of code is not entirely safe.
>
> It also doesn't work correctly if IFS was unset. You will "restore"
> IFS to an empty value, instead of unsetting it. The two behave very
> differently.
>
>> OLD_IFS="$IFS"
>> IFS=$'\n'
>> array=($(printf "%s\n" 'a b' 'c d'))
>> IFS="$OLD_IFS"
>
> Your array assignment is not safe, and is quite silly. Just do this
> instead:
>
> array=('a b' 'c d')
>
> Now, you are probably going to say "But but but but it was just an
> example, my real code is like ....". Please show the REAL code
> instead, or at least a framework that has the same characteristics
> as the real code.
>
> If you are trying to read the output of an arbitrary program into an
> array (line by line), do it like this in bash 4.x:
>
> readarray -t array < <(my program)
>
> Or like this in bash 3.1 and up:
>
> array=()
> while IFS= read -r line; do
> array+=("$line")
> done < <(my program)
> array+=("$line") # omit if you want to discard trailing incomplete line
>
> Or like this in bash 2 through 3.0:
>
> array=() i=0
> while IFS= read -r line; do
> array[i++]=("$line")
> done < <(my program)
> array[i++]=("$line") # omit if you want to discard trailing incomplete line
>
> DO NOT write code like array=($(...)). It will fail in unexpected ways
> when you start giving it arbitary inputs. Setting IFS is not enough to
> protect you.
OK. Thank you for your advice.
I'm trying to understand readarray. It can only separate elements by
newline. What about separating the elements by $'\0'? Is there an
option for this case (I don't find it in the man page)?
#!/usr/bin/env bash
readarray -t array < <(find . -type f -print0)
printf "%s\n" "address@hidden"
readarray -t array < <(printf '%s\n' 'a b' 'c d')
printf "%s\n" "address@hidden"
--
Regards,
Peng