How to do? Possible?
I got great help in learning about how to do the perl equiv of (var1, var2, var3)= (list) using read var1 var2 var3 <<<(list). I use it often to get back lists of values from subroutine calls, but with sometimes useful, and sometimes hindering fact that when I do read var1 var2 var3 <<<$(function x y z) function's ability to affect the global env, is 'nixed', is there something like a read var1 var2 var3 <<<${function x y z), that would do the same, but like {} in code, wouldn't put the contents in a sub proc? I can think of uglier looking ways to get around it, but was hoping for something more elegant. Truth be told, I split a file that was growing too large that had a mix of functions and calls to them, by putting the functions into a separate lib but I'd like the lib to be a bit more general and keep it's own state (shared with the parent or not, wouldn't matter in my design), but as the function calls are called in the (), there seems to be no easy way to export them to anything that will be shared
Re: How to do? Possible?
On Mon, Jul 25, 2011 at 12:20 PM, Linda Walsh wrote: > > > > I got great help in learning about how to do the perl equiv of (var1, > var2, var3)= (list) using read var1 var2 var3 <<<(list). > > I use it often to get back lists of values from subroutine calls, but with > sometimes useful, and sometimes hindering fact that when I do > read var1 var2 var3 <<<$(function x y z) > > function's ability to affect the global env, is 'nixed', Since you are already using global variables, why not simply use a couple more for the return values?
``complete -d -o default cd'' issue
For example: [bash-4.2.8] # ls -lF total 4 drwxr-xr-x 3 root root 4096 2011-07-25 16:52 long-dir-name.d/ [bash-4.2.8] # ls -lF long-dir-name.d/ total 4 drwxr-xr-x 2 root root 4096 2011-07-25 16:52 bar/ [bash-4.2.8] # complete -d -o default cd [bash-4.2.8] # cd *.d Here the cannot expand ``*.d'' to ``long-dir-name.d''. Bug?
Re: Built-in printf Sits Awkwardly with UDP.
Hi Chet, > On 7/22/11 10:38 AM, Ralph Corderoy wrote: > > On a related note, I can't interrupt this, e.g. Ctrl-C. > > > > printf '%-92233720368547758q.\n' foo > > That's interesting, since the fieldwidth (and precision) end up > getting set to 0 if they overflow INT_MAX, at least on my machine, and > the result is more or less instantaneous. I agree that bash should do > the same thing in printstr when presented with an overflowing field > width that it does when using getint(). I will look at making that > change. I also get, with vanilla 4.2 built from source, $ ./install/bin/bash -c "printf '%*q.\n' 10 foo -20 bar 0x8000" foo. bar . Segmentation fault (core dumped) $ Cheers, Ralph.
Re: How to do? Possible?
On 7/25/2011 5:20 AM, Linda Walsh wrote: I got great help in learning about how to do the perl equiv of (var1, var2, var3)= (list) using read var1 var2 var3<<<(list). I use it often to get back lists of values from subroutine calls, but with sometimes useful, and sometimes hindering fact that when I do read var1 var2 var3<<<$(function x y z) function's ability to affect the global env, is 'nixed', is there something like a read var1 var2 var3<<<${function x y z), that would do the same, but like {} in code, wouldn't put the contents in a sub proc? I can think of uglier looking ways to get around it, but was hoping for something more elegant. Truth be told, I split a file that was growing too large that had a mix of functions and calls to them, by putting the functions into a separate lib but I'd like the lib to be a bit more general and keep it's own state (shared with the parent or not, wouldn't matter in my design), but as the function calls are called in the (), there seems to be no easy way to export them to anything that will be shared I highly recommend reading this, but read it *very carefully*. I have adopted this in my production system and it works great. The idea is to implement passing variables by reference and to allow the values to be either scalars or arrays. It sounds like you would benefit from this. http://fvue.nl/wiki/Bash:_Passing_variables_by_reference -- Time flies like the wind. Fruit flies like a banana. Stranger things have .0. happened but none stranger than this. Does your driver's license say Organ ..0 Donor?Black holes are where God divided by zero. Listen to me! We are all- 000 individuals! What if this weren't a hypothetical question? steveo at syslang.net
Re: ``complete -d -o default cd'' issue
"Clark J. Wang" writes: > Here the cannot expand ``*.d'' to ``long-dir-name.d''. Bug? You need to add -o bashdefault for that. Andreas. -- Andreas Schwab, sch...@linux-m68k.org GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."
Re: How to do? Possible?
Pierre Gaston wrote: > Since you are already using global variables, why not simply use a > couple more for the return values? > --- Because a subshell cannot access the global variables of the parent. The only 'hack' I came up with overnight for a quick & dirty, is to pass back a "blob" along with the 3 return values the function normally returns, which the parent will 'eval' in the parent context (contain 'export XXX=value' or 'alias xxx=/path' statements. The purpose of this was to pre-verify the needed external utilities the script would be using -- their paths and their existence so the script would be less likely to fail non-deterministically later on.
Re: How to do? Possible?
> Because a subshell cannot access the global variables of the > parent. > A subshell can access its parent's variables. foo=bar; ( echo "$foo" ) A sub process cannot, unless the variables are exported. It does not sound like you need to do so here.
Re: How to do? Possible?
Steven W. Orr wrote: > On 7/25/2011 5:20 AM, Linda Walsh wrote: > I highly recommend reading this, but read it *very carefully*. I have > adopted this in my production system and it works great. The idea is to > implement passing variables by reference and to allow the values to be > either scalars or arrays. It sounds like you would benefit from this. > > http://fvue.nl/wiki/Bash:_Passing_variables_by_reference Looks very interesting...will have to peruse it... I'm starting to use eval more often -- generally haven't because I thought it to be slow, but realistically, and as the article states, with hard-timings, it's faster than expression in a sub-process... That could lead to much more flexibility (besides benefit of speed). Thanks!
Re: How to do? Possible?
On Mon, Jul 25, 2011 at 8:33 PM, Linda Walsh wrote: > Pierre Gaston wrote: >> Since you are already using global variables, why not simply use a >> couple more for the return values? >> > --- > Because a subshell cannot access the global variables of the > parent. uh? you don't make sense. 1) a subshell can access the parent variables just fine 2) your intial problem was to avoid the subshell of your solution to be able to use global variables I'm just saying : foo () { ret1=blah;ret2=bleh; }; foo;echo $ret1 $ret2
Re: How to do? Possible?
DJ Mills wrote: >> Because a subshell cannot access the global variables of the parent. > > A subshell can access its parent's variables. foo=bar; ( echo "$foo" ) > > A sub process cannot, unless the variables are exported. It does not sound > like > you need to do so here. I'm not sure about your terminology -- a subshell is a subprocess. By my understanding, "{}" defines a complex statement and "()" defines both a subshell which is in a separate process, i.e. subshell=sub process, but aside from 'symantic' issues, I didn't really say fully what I meant -- you would have to read it in context of the previous message where the idea was to 'set' the global vars in the subshell (not in a complex statement) (ex. A, below) OR be able use a complex statement in place of a subshell after "<<<" (ex. B, below) Pierre Gaston wrote: > On Mon, Jul 25, 2011 at 8:33 PM, Linda Walsh wrote: >> Pierre Gaston wrote: >>> Since you are already using global variables, why not simply use a >>> couple more for the return values? >>> >> --- >>Because a subshell cannot access the global variables of the >> parent. > > uh? you don't make sense. > 1) a subshell can access the parent variables just fine > 2) your intial problem was to avoid the subshell of your solution to > be able to use global variables > > I'm just saying : foo () { ret1=blah;ret2=bleh; }; foo;echo $ret1 $ret2 > Arg:... I'm hard to interpret, but, but that's cuz, gaston, ya got me confused and off track, and I responded to what you said within the context of what I was trying to do (set global variables in the function that also returned values). I had originally: A) read var1 var2 var3 <<<$(function a b c); (where what I mean was function was the name of some random function, which I would hope could be gathered from syntax) What I wished for was B) read var1 var var3 <<<${func a b c} where I not only could have func pass back explicit return values, but also, operate in the context of the parent, thus being able to affect the parent's env vars. The first form is the only form that works AFAIK, the 2nd form is what I want to do ... gaston replied: Since you are already using global variables, why not simply use a couple more for the return values? --- Ok, here's where things got confusing. I gave A & B and you responded with something that fell out of my example paradigm -- a function returning explicit values, but also being able to effect the global ENV. So I, first thing in the morning, I thought you were thought you were asking "why not have $(function a b c) just return vals in 'global variables'"? (which, I understand now, isn't what you meant). That's why I responded that the subshell can't access [for purposes of SETTING (*context*)), global vars... So...now that that's all explained. there's still the original want... (am still experimenting w/the 'pass-by-value stuff that DJMills referred to, trying to flesh out a few more odd cases..., so of course I end up writing a program to handle it all (got to complex doing all in interactively). will keep you posted if you are interested...
bug? {1..3} doesnt' use IFS to separate fields
I know it wasn't designed this way, but it seems like it is a bug. If I do read a b c <<<$(echo {1..3} ); echo "a:$a b:$b c:$c" I get: a:1 b:2 c:3 But If I do export IFS=','; read a b c <<<$(echo {1..3} ); echo "a:$a b:$b c:$c" I get: a:1 2 3 b: c: Why should the 2nd case return the wrong answer? I.e. shouldn't {1..3} use the IFS to separate arguments?
Re: How to do? Possible?
Linda Walsh wrote: > DJ Mills wrote: > >> Because a subshell cannot access the global variables of the parent. > > > > A subshell can access its parent's variables. foo=bar; ( echo "$foo" ) > > > > A sub process cannot, unless the variables are exported. It does > > not sound like you need to do so here. > > I'm not sure about your terminology -- a subshell is a > subprocess. By my understanding, "{}" defines a complex statement > and "()" defines both a subshell which is in a separate process, Yes, but it is a fork(2) of the parent shell and all of the variables from the parent are copied along with the fork into the child process and that includes non-exported variables. Normally you would expect that a subprocess wouldn't have access to parent shell variables unless they were exported. But with a subshell a copy of all variables are available. Bob
Re: How to do? Possible?
Bob Proulx wrote: > Linda Walsh wrote: >> DJ Mills wrote: Because a subshell cannot access the global variables of the parent. >>> A subshell can access its parent's variables. foo=bar; ( echo "$foo" ) >>> >>> A sub process cannot, unless the variables are exported. It does >>> not sound like you need to do so here. >> I'm not sure about your terminology -- a subshell is a >> subprocess. By my understanding, "{}" defines a complex statement >> and "()" defines both a subshell which is in a separate process, > > Yes, but it is a fork(2) of the parent shell and all of the variables > from the parent are copied along with the fork into the child process > and that includes non-exported variables. Normally you would expect > that a subprocess wouldn't have access to parent shell variables > unless they were exported. But with a subshell a copy of all > variables are available. > > Bob -- Not really. It only seems that way because within () any "$" is usually expanded BEFORE the () starts from the parent You can see this by GLOBAL="hi there" (echo $GLOBAL) prints out "hi there" as expected, but if we hide $GLOBAL so it isn't seen by parent: (foo=GLOBAL; echo ${!foo}) prints "" So, they aren't really available in a subshell, only that a subshell's contents are evaluated before the subshell is called.
Re: How to do? Possible?
Linda Walsh wrote: > > Bob Proulx wrote: >> Yes, but it is a fork(2) of the parent shell and all of the variables >> from the parent are copied along with the fork into the child process >> and that includes non-exported variables. Normally you would expect >> that a subprocess wouldn't have access to parent shell variables >> unless they were exported. But with a subshell a copy of all >> variables are available. >> >> Bob > -- > Not really. > It only seems that way because within () any "$" is usually > expanded BEFORE the () starts from the parent > > You can see this by > GLOBAL="hi there" > (echo $GLOBAL) > prints out "hi there" as expected, but if we hide > $GLOBAL so it isn't seen by parent: > (foo=GLOBAL; echo ${!foo}) > prints "" --- I mistyped that but it brings me to an interesting conundrum: GLOBAL="hi there" {foo=GLOBAL echo ${!foo}; } > (foo=GLOBAL echo ${!foo} ) But: > { foo=GLOBAL;echo ${!foo}; } hi there > (foo=GLOBAL; echo ${!foo}) hi there Weird...
Re: How to do? Possible?
On 07/25/2011 03:45 PM, Linda Walsh wrote: I mistyped that but it brings me to an interesting conundrum: GLOBAL="hi there" {foo=GLOBAL echo ${!foo}; } This says: evaluate ${!foo}, and pass that expansion to 'echo', with foo=GLOBAL in the environment of echo. You are invoking behavior that POSIX leaves undefined (that is, bash is perfectly fine evaluating ${!foo} prior to assigning foo, but bash would also be okay if it assigned foo prior to evaluating ${!foo}. Hence, you got no output. But: { foo=GLOBAL;echo ${!foo}; } > hi there The extra ; forces the semantics. Here, the assignment to foo is a different statement than the expansion of of ${!foo}. And while ${!foo} is a bash extension, it still proves that this is a case where foo was assigned prior to its use. Weird... Not if you think about it properly. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org
Re: How to do? Possible?
On Mon, 25 Jul 2011 14:28:52 -0700, Linda Walsh wrote: > Not really. > It only seems that way because within () any "$" is usually > expanded BEFORE the () starts from the parent > > You can see this by > GLOBAL="hi there" > (echo $GLOBAL) > prints out "hi there" as expected, but if we hide > $GLOBAL so it isn't seen by parent: > (foo=GLOBAL; echo ${!foo}) > prints "" > > So, they aren't really available in a subshell, only > that a subshell's contents are evaluated before the subshell is > called. There is a distinction to make between exported and non-exported variables. Also, foo=bar command is quite different from foo=bar; command (although sometimes, under certain conditions, they may appear to yield the same result). -- D.
Re: How to do? Possible?
Eric Blake wrote: > On 07/25/2011 03:45 PM, Linda Walsh wrote: >> I mistyped that but it brings me to an interesting >> conundrum: >> >> GLOBAL="hi there" >> {foo=GLOBAL echo ${!foo}; } > > This says: > > evaluate ${!foo}, and pass that expansion to 'echo', with foo=GLOBAL in > the environment of echo. You are invoking behavior that POSIX leaves > undefined... > >> Weird... > > Not if you think about it properly. --- Didn't think it was a bug. just 'odd', and that's because it falls into a POSIX undefined case, that could really go 'either way'...as you seemed to state. I didn't know why it behaved differently, but as you informed me the difference is 'one's well-defined, and the other is not, I can see why there 'could' be a difference... ;-) (which of course could change tomorrow, I suppose..)
Re: How to do? Possible?
Linda Walsh wrote: > I didn't know why it behaved differently, but as you informed me > the difference is 'one's well-defined, and the other is not, I can > see why there 'could' be a difference... ;-) > > (which of course could change tomorrow, I suppose..) Not the second well defined case. It can't change without being in conflict with the standards. You would always be safe to use it in any standard conforming shell. If you are still not convinced then consider these next two examples. #!/bin/sh printfoovar() { echo $foo ;} foo="bar" ( printfoovar ) #!/bin/sh printfoovar() { eval echo \$$foo ;} bar="hello" foo="bar" ( printfoovar ) Bob
Re: How to do? Possible?
On Mon, Jul 25, 2011 at 4:45 PM, Linda Walsh wrote: > > > Linda Walsh wrote: >> >> Bob Proulx wrote: >>> Yes, but it is a fork(2) of the parent shell and all of the variables >>> from the parent are copied along with the fork into the child process >>> and that includes non-exported variables. Normally you would expect >>> that a subprocess wouldn't have access to parent shell variables >>> unless they were exported. But with a subshell a copy of all >>> variables are available. >>> >>> Bob >> -- >> Not really. >> It only seems that way because within () any "$" is usually >> expanded BEFORE the () starts from the parent >> >> You can see this by >> GLOBAL="hi there" >> (echo $GLOBAL) >> prints out "hi there" as expected, but if we hide >> $GLOBAL so it isn't seen by parent: >> (foo=GLOBAL; echo ${!foo}) >> prints "" > --- > I mistyped that but it brings me to an interesting > conundrum: > > GLOBAL="hi there" > {foo=GLOBAL echo ${!foo}; } > >> (foo=GLOBAL echo ${!foo} ) > > But: >> { foo=GLOBAL;echo ${!foo}; } > hi there >> (foo=GLOBAL; echo ${!foo}) > hi there > > Weird... > > > I'm assuming you meant: GLOBAL="hi there" {foo=$GLOBAL echo ${!foo}; } You had a missing dollar sign. -- Visit serverfault.com to get your system administration questions answered.
Re: Built-in printf Sits Awkwardly with UDP.
On 7/25/11 8:49 AM, Ralph Corderoy wrote: > I also get, with vanilla 4.2 built from source, > > $ ./install/bin/bash -c "printf '%*q.\n' 10 foo -20 bar 0x8000" >foo. > bar . > Segmentation fault (core dumped) > $ Thanks for the report. That's a different problem, caused by a missing argument that printstr (via getint) doesn't handle very well. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: ``complete -d -o default cd'' issue
On Tue, Jul 26, 2011 at 12:00 AM, Andreas Schwab wrote: > "Clark J. Wang" writes: > > > Here the cannot expand ``*.d'' to ``long-dir-name.d''. Bug? > > You need to add -o bashdefault for that. > ``-o bashdefault'' works fine for me, thanks. But from the Bash manual I think ``-o default'' should also work: -o defaultUse readline's default filename completion if the compspec generates no matches. -Clark > > Andreas. > > -- > Andreas Schwab, sch...@linux-m68k.org > GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 > "And now for something completely different." >
Re: How to do? Possible?
Dennis Williamson wrote: > Linda Walsh wrote: > > GLOBAL="hi there" > > {foo=GLOBAL echo ${!foo}; } Note that this tickles a problem since foo isn't set before $foo is expanded. Use this following with a semicolon instead: GLOBAL="hi there" {foo=$GLOBAL; echo ${!foo}; } > You had a missing dollar sign. > > I'm assuming you meant: > > GLOBAL="hi there" > {foo=$GLOBAL echo ${!foo}; } Er.. No. There is a missing semicolon as described above and in other messages in the thread but the dollar size is intended to be excluded so that foo contains the string "GLOBAL" and ${!foo} will indirect through it. The magic is the ${!parameter} syntax. If you look at the bash documentation for ${parameter} you will find the following documentation. The second paragraph explains the '!' part and is the part needed to understand the indirection. ${parameter} The value of parameter is substituted. The braces are required when parameter is a positional parameter with more than one digit, or when parameter is followed by a character which is not to be interpreted as part of its name. If the first character of parameter is an exclamation point (!), a level of variable indirection is introduced. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion. The exceptions to this are the expansions of ${!prefix*} and ${!name[@]} described below. The exclamation point must immediately follow the left brace in order to introduce indirection. And so as you can see from this ${!foo} expands the value of foo to be the string "GLOBAL" and then continues using that as an indirection and expands the value of $GLOBAL. With echo ${!foo} it would be very similar to saying 'eval echo \$$foo'. It would dynamically indirect through and pick up the value of GLOBAL. You can tell the difference by changing the value of GLOBAL between echo statements. Static direct binding: #!/bin/bash GLOBAL="one" foo=$GLOBAL { echo ${foo}; } GLOBAL="two" ( echo ${foo} ) Emits: one one Dynamic indirect binding: #!/bin/bash GLOBAL="one" foo=GLOBAL { echo ${!foo}; } GLOBAL="two" ( echo ${!foo} ) Emits: one two And the difference between using {...} and (...) is back to the original discussion of the thread that subshells have access to copies of all parent variables including variables that were not explicitly exported. Hope that helps to clarify things. Bob
Re: How to do? Possible?
Sorry, I overlooked the indirection (and the missing semicolon). On Mon, Jul 25, 2011 at 10:18 PM, Bob Proulx wrote: > Dennis Williamson wrote: >> Linda Walsh wrote: >> > GLOBAL="hi there" >> > {foo=GLOBAL echo ${!foo}; } > > Note that this tickles a problem since foo isn't set before $foo is > expanded. Use this following with a semicolon instead: > > GLOBAL="hi there" > {foo=$GLOBAL; echo ${!foo}; } > >> You had a missing dollar sign. >> >> I'm assuming you meant: >> >> GLOBAL="hi there" >> {foo=$GLOBAL echo ${!foo}; } > > Er.. No. There is a missing semicolon as described above and in > other messages in the thread but the dollar size is intended to be > excluded so that foo contains the string "GLOBAL" and ${!foo} will > indirect through it. > . . . > Bob > -- Visit serverfault.com to get your system administration questions answered.