Re: parameter expansion with `:` does not work
On Thu, Jul 08, 2021 at 04:38:25AM +0200, lisa-as...@perso.be wrote: > I'd rather understand what's going on, rather than simply never use it. OK. Let's start from the beginning. In sh and bash, anything that begins with a $ is potentially a substitution, a.k.a. an expansion. The parser will try to unravel the punctuation soup to figure out where the beginning and ending of the substitution are. Then, that piece of the command will be replaced with zero or more words. All of it is dependent on context, and rules that have grown organically and chaotically over a span of decades. Let's say you have a command like this: foo $bar The thing on the right hand side, which begins with $ and ends with r, is a substitution. Specifically, it's a parameter expansion, which means a "parameter" (which is either a variable or a special parameter, in this case a variable) will have its value pulled from memory and used for the substitution. If we have a variable named bar, its value gets substituted into the command. Since $bar is not quoted, that value undergoes two more rounds of substitutions (word splitting, and filename expansion). At the end of all that action, we will have a list of zero or more words, and these words will become the arguments of the foo command. OK so far? Good. Now let's say we have this command: : $bar Once again, the value of the variable named bar is substituted, and then undergoes word splitting and filename expansion, and the results of that become the arguments to the : command. The : command does nothing, so the end result of all this work is ... nothing. Except that we may hit the file system a few times in order to perform filename expansions, if there are any glob characters in the variable's value. But that's it. So, why would anyone write a command like this? It's because some substitutions have side effects. Let's look at this command next: : $((x++)) Now, this is a silly command, and you wouldn't write this in real life, because it's just more complex than it needs to be. But I'm demonstrating something, so stick with it for a moment, please. This time, we don't have a parameter expansion. We have an arithmetic substitution instead. The stuff inside the $(( )) gets passed to a special arithmetic parser, which has its own special rules. These rules look a lot like the rules of the C language, by some strange coincidence. This particular arithmetic expression x++ uses the post-increment operator ++ to add 1 to the value of an existing (or even nonexistent) variable. This is a *side effect*, meaning that it does something more than just producing a value for our substitution. It has some lasting effect. So, what happens here? In order: 1) The value of x is pulled from memory and stored in a temporary spot. If x doesn't exist, we use the value 0. If x contains a string that can be treated as an integer, we use that value. Otherwise, we attempt to perform recursive arithmetic evaluation. We won't cover all of that right now. 2) We take the value from step 1, add 1 to it, and store this back into x. 3) The value from step 1 (before we added 1) is used as the value of the substitution. 4) The value of the substitution would undergo word splitting and filename expansion because of the lack of quotes, except that the result of an arithmetic expansion is always an integer, and therefore can't do those things. 5) The value of the substitution is used as the argument of the : command, which does nothing. So, the whole point of this demonstration was what happens in step 2. The value of x is changed, even though we used a command that normally does nothing. The change happens *during* the expansion. It's independent of the command that we used. The only reason we have the : command here at all, is so that we don't try to execute the value of x as a command. If we left out the : we would get something like bash: 0: command not found We don't want that. So that's why the : is there. Now that you understand everything that's going on, let's look at this crazy shit from 1977 that you've fallen in love with: : ${foo:=bar} What happens here? We have a parameter expansion with a special modifier. According to the documentation which has been quoted at you multiple times already, this is a two-step expansion. The value of the variable named foo is pulled from memory. If this value is the empty string, or if the variable foo does not currently exist, then an *assignment* takes place, and the string bar is stored in the variable foo, and then that string (bar) also becomes the value of the substitution. So, we perform the following steps: 1) The value of the variable foo is pulled from memory. 2) If the value from step 1 is the empty string (or if there's no variable named foo yet), the string bar is *assigned* to the variable foo, and the string bar also becomes the value that we pulled from memory. 3) The
Re: parameter expansion with `:` does not work
> On Jul 7, 2021, at 10:38 PM, lisa-as...@perso.be wrote: > > Correct. How do others customarily use `${fdir:=$PWD}` ? The common idiom is : "${fdir:=$PWD}" The ':' utility is used because it does nothing, but its arguments are expanded as usual. > I'd rather understand what's going on, rather than simply never use it. Think about what is happening here: fdir=${fdir:=$PWD} This is conceptually equivalent to if [[ -z "$fdir" ]]; then fdir="$PWD" fi fdir="$fdir" I hope you can see why this is a pointless thing to do. -- vq
Re: parameter expansion with `:` does not work
On Thu, 8 Jul 2021 02:54:06 +0200 (CEST) lisa-as...@perso.be wrote: > As I was in it, have also changed > > > > fdir=${fdir:-$PWD} This makes sense. > > > > to > > > > fdir=${fdir:=$PWD} Here, you are using a form of parameter expansion that intrinsically performs variable assignment, only to redundantly assign the result of the expansion to the same variable once again. In a roundabout fashion, it ends up proving Greg's point. I'd suggest temporarily disavowing yourself of the ${parameter:=word} form, for the time being. -- Kerin Millar
Re: parameter expansion with `:` does not work
> > fdir=${fdir:=$PWD} > > Ack! I know. I simply gave up. At least this will "work", even if it's completely silly.
Re: parameter expansion with `:` does not work
On Wed, Jul 7, 2021, 7:55 PM wrote: > > > Things are clearer now. > > > > > Seriously, just replace the :- expansion with := and go on with your > code. > > It's the least intrusive change, and won't disturb your logic. > > > > I executed > > > > echo "${parameter:-word}"; echo "${parameter}" > > > > and then > > > > echo "${parameter:=word}"; echo "${parameter}" > > > > It was to make the distinction clear. > > > > As I was in it, have also changed > > > > fdir=${fdir:-$PWD} > > > > to > > > > fdir=${fdir:=$PWD} > > > > Ack!
Re: parameter expansion with `:` does not work
On 7/7/21 6:53 PM, lisa-as...@perso.be wrote: Yes I can see one has :- and the other has := But I also noticed : at the front, with someone saying that the command does not exist in Gnu Bash. No one implied that `the command' is not present in bash. Seriously, just replace the :- expansion with := and go on with your code. It's the least intrusive change, and won't disturb your logic. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: parameter expansion with `:` does not work
On Thu, Jul 08, 2021 at 12:33:04AM +0200, lisa-as...@perso.be wrote: > Talking about neater design choices, you seem to imply you have some other > way to take user options that are composed of lists, so that one does not use > a delimited string. What is it? I wrote a detailed message containing many different choices: https://lists.gnu.org/archive/html/help-bash/2021-07/msg00019.html
Re: parameter expansion with `:` does not work
On 7/7/21 6:48 PM, lisa-as...@perso.be wrote: I have some difficulty understanding the difference between ${parameter:-word} and ${parameter:=word}, and when it is appropriate to use one as opposed to the other. Dennis Williamson succinctly summarized the differences. ${parameter:-word} If parameter is unset or null, the expansion of word is substituted. ${parameter:=word} If parameter is unset or null, the expansion of word is assigned to parameter. The value of parameter is then substituted. The key difference is in the first sentence of each description. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: parameter expansion with `:` does not work
On Thu, Jul 08, 2021 at 12:37:07AM +0200, lisa-as...@perso.be wrote: > >From: Dennis Williamson > >$ : ${foo:-bar} > >$ : ${foo:=bar} > >The first form is a substitution and the second form is an assignment. > So you used `:` at the beginning and it worked? Are you incapable of seeing the difference between the two lines? I weep for the human race. There's no telling what you're even seeing on your monitor (assuming you can see, and aren't using a screen reader). You're clearly using some mail user agent that works like Microsoft Outlook, and there's no guessing what it's doing to the messages you receive. If you literally cannot see the difference between :- and := in the above example, then all is lost, and there is nothing more we can say to you. Because you can't see it.
Re: parameter expansion with `:` does not work
On Wed, Jul 7, 2021, at 6:37 PM, lisa-as...@perso.be wrote: > So you used `:` at the beginning and it worked? Chet and Greg already spelled out your mistake. It has nothing to do with the ':' command. -- vq
Re: parameter expansion with `:` does not work
On Wed, Jul 7, 2021, 4:50 PM wrote: > > Have noticed that parameter expansion with `:` does not work > > > > : ${fltype:-"texi,org"} # alternative to `fltype=` > > $ unset foo $ : ${foo:-bar} $ echo "$foo" $ : ${foo:=bar} $ echo "$foo" bar The first form is a substitution and the second form is an assignment.
Re: parameter expansion with `:` does not work
On Thu, Jul 08, 2021 at 12:10:27AM +0200, lisa-as...@perso.be wrote: > The line > : ${fltype:-"texi,org"} > should be an alternative to > fltype=${fltype:-"texi,org"} As Chet guessed earlier, you probably meant := instead of :- . I started typing something to that effect in my first response, but then I noticed the payload you were "assigning" (though you messed up the syntax) and decided to try to teach you to fish, rather than tossing you the decrepit, smelly old fish you had dropped in the dirt. You are using horrible syntax to do the *wrong thing*. Lists should be stored in indexed array variables, not in strings with silly delimiters. Initialize an array variable holding the default list of extensions at the beginning of your program. Then, in your option-processing code, if the user supplies their own delimited list of extensions, split it apart and use the resulting list to overwrite the array variable. That's it. No need for 40-year-old crappy syntax. No need to store your default list as a delimited string and then spend system resources splitting it apart. You only need to expend those resources if the user supplies a delimited list, and the user only needs to do that because of the crappy design choices you've made. But since the user is you, if that's how you *really* want the program to work, then so be it. Just don't make it even worse than it needs to be.
Re: parameter expansion with `:` does not work
On 7/7/21 6:12 PM, lisa-as...@perso.be wrote: > : ${fltype:-"texi,org"} # alternative to `fltype=` > I'm not sure why you think that's an alternative. Maybe you meant ${fltype:="texi,org"}? It is supposed to be built into bash so a new process is not created. Perhaps not in Gnu Bash? What are you talking about? What do you think you're saying? -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: parameter expansion with `:` does not work
On 7/7/21 6:10 PM, lisa-as...@perso.be wrote: The line : ${fltype:-"texi,org"} should be an alternative to fltype=${fltype:-"texi,org"} It absolutely is not. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: parameter expansion with `:` does not work
On 7/7/21 5:50 PM, lisa-as...@perso.be wrote: Have noticed that parameter expansion with `:` does not work : ${fltype:-"texi,org"} # alternative to `fltype=` > I'm not sure why you think that's an alternative. Maybe you meant ${fltype:="texi,org"}? -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: parameter expansion with `:` does not work
On Wed, Jul 07, 2021 at 11:50:01PM +0200, lisa-as...@perso.be wrote: > Have noticed that parameter expansion with `:` does not work > > : ${fltype:-"texi,org"} # alternative to `fltype=` What did it do? What did you *expect* it to do? This looks like it's related to your ongoing project to make your simple script as complex as possible. As such, it appears you're digging into the bowels of the Bourne shell and trying to dig up every obscure piece of syntax you can find, so that you can use them all, to be completely sure you can't possibly read the script a week from now. I advise you to stop doing this. In this particular instance, you're assigning a LIST of two values to a STRING variable, using a comma as a delimiter between them. Presumably you're going to split this list apart later on. Wouldn't it be a whole lot simpler to store the list in an ARRAY variable in the first place, and avoid the need to split it?