help-bash
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]