last day (17 days later) » 

16:13
1
A: If [ is a builtin and [[ is a keyword, then what is ((?

Gilles(( is not a word. Unlike [ and [[, it isn't part of the list of words that constitutes a command. The best way to think of it is as punctuation. Actually, it's two punctuation characters, which may or may not be combined in a single token depending on the context. It's similar to things like >& a...

|| is a "control operator", even more it is an "AND and OR lists" operator; >& is a "redirection operator" which could be placed at any place of a valid command line. Could you post a place where ( is defined as a punctuation character in bash? Even more, where is "punctuation" in shell syntax defined ?
@sorontar The POSIX standard doesn't have a word for the category that encompasses all punctuation, and neither does the bash documentation. It's a word that I use because the meaning is intuitively comprehensible. Tokens like || and >& fit in the general category of “operators” because they have an infix syntax. You can also classify (( as an operator, but it isn't as common because it's really only half of the (()) operator.
Hi, @Gilles , Thank you for answer. I know that spaces is important in bash. But why space is not relevant inside (( ))
@user15964 Spaces are not significant inside ((…)) or $((…)) because the shell's parser doesn't care about spaces while it's parsing an arithmetic expression. The language of arithmetic expressions is designed that way because there's no place in the language where spaces would be useful. In particular, in an arithmetic expression, there are never two words next to each other, which is where spaces are the most critical.
No, @Gilles, Calling a (( "punctuation" is as reasonable as calling an if "punctuation". That is incorrect.
16:13
Note that (( is also found in ((echo foo; echo bar) | grep o). ksh's ((arith)) conflicts with nested (subshell) which is why POSIX tells you do use ( (subshell)) (even though it doesn't specify ((arith))).
@StéphaneChazelas In such case the (( becomes a(list), much like adding an space. I already covered that in my answer.
@sorontar, yes though you don't cover the fact that ((...)) doesn't always mean an arithmetic expression. ((uname)) is a nested subshell in all shells that don't implement ksh ((arithmetics)). And ((foo);(bar)) is not arith in any shell.
@StéphaneChazelas Well, yes, if ((arithmetics)) is not implemented it hardly could be an arithmetic anything. And, as I said: (( introduces a compound command (much like if, or for, or case) which needs the rest of the structure {a closing )) in the (( case} as the others also need the correct rest of the corresponding structure. An if without a fi is usually a syntax error in all shells.
@sorontar, not sure we're talking of the same thing. ((echo x; echo y) | grep x) has a (( without a closing )) and is not an arithmetic expression. bash calls compound command anything that is not a simple command which includes both ((a==b)) and ((echo x; echo y)|grep x)
@StéphaneChazelas Bash and ksh both use the (not a simple command). And nope. A (( without a closing )) is not a compound command, not in ksh nor in bash. Your example is similar to if true; then echo yes; f i. It doesn't work, it is an incomplete command in the case of if and falls down to something else in the case of the double parenthesis.
16:13
@sorontar, I don't follow. ((echo x; echo y)|grep x) works and is a compound command in any shell.
@StéphaneChazelas No it is a couple of (lists).
@StéphaneChazelas Which work exactly the same as ( (echo x; echo y) | grep x ). But ( ( 2+2) ) or even ((2+1) ) do not work.
@StéphaneChazelas Even in old dash: Commands may be grouped by writing either (list) … …
@sorontar. Yes. Now we agree that (( doesn't only start an arithmetic expression, it can also start a nested subshell which is the point I'm trying to make since the start.
@StéphaneChazelas To which I answered: becomes a (list) which is exactly the same as now you are agreeing to accept. <sigh>. Just to prove the point (in bash): ((echo $BASHPID)|cat;echo $BASHPID). Each subshell has its number. Which an arithmetic expression will not need: echo $BASHPID;((a=BASHPID+0)); echo $a.
@StéphaneChazelas In your example there is not one atomic (( but there are two ( which happen to appear together. They are not one element, exactly as ( (echo x; echo y) | grep x ) works.
@sorontar, Yes. In both ((1+1)) and ((id);(uname)) the shell sees a (( token, but needs to look further ahead to decide whether we're in a arithmetic expansion or nested subshell case (or combination like in (((1+1)); (id))). And the rules vary between shells. See for instance bash -c $'((uname)\n(uname))' that doesn't work (works in ksh and zsh). And in ksh93 (((1+1)); (id)) doesn't work (in that ((1+1)) is taken as a nested sub-shell
@StéphaneChazelas But this: bash -c $'( (uname)\n(uname) )' and this bash -c '((uname);(uname))' both work. Again: two ( doesn't always make one ((.
16:13
Yes, adding the extra space is the best way to remove the potential ambiguity. Related: austingroupbugs.net/bug_view_page.php?bug_id=217
@StéphaneChazelas Yes, there may be ambiguity between two potential interpretations of two different structures, thus, the space. But the point with @Gilles is: what an unambiguous (( (with the corresponding correct closing )) ) should be called? "Punctuation" seems incorrect to me.
@sorontar, one could say something like the (( lexical token when in command position and followed by a valid arithmetic expression and )) starts an arithmetic expression command. But I'd rather say that ((valid arithmetic expression)) when found in command composition is a compound command that evaluates the expression and returns an exit status accordingly (true for non-zero). IOW, I don't find it important/interesting what you may call that (( part of the ((...)) command.
@sorontar, punctuation doesn't seem a bad terminology choice to me. In English, you have words, space and punctuations, words giving the substance, and space/punctuation giving the structure. In the shell language, blanks, (, > are never part of WORD tokens (at least not when not-quoted), so could be seen as punctuation. That's how I understand @Gilles' answer.
@StéphaneChazelas Leaving aside the point that words (or more technically called "tokens") in shell are different than in "English Language" and therefore follow different rules. For example, (( becomes a word (token) in shell syntax, but it can not be a word in English (it is not "only letters"). ... ... So, an if (which is also the introduction of a compound command) may be correctly called "punctuation"? Do you really mean that?
16:29
@sorontar, if [[ is a keyword, then yes, why not call (( (which is not a word in the sh language but a special token participating in the structure of the language) punctuation. That makes sense to me.
16:40
A `[[` is a (key)**word** in the sense that it require spaces (metacharacters) around it to be correctly recognized. A `((` does not require spaces around it as it itself guides the lexer to break it into a "word" (token).
For example: unset a b;((a=33))&&((b=34));echo $a $b. The (( used needed no special spaces to be correctly parsed.
In that sense, a (( is different, and should not be called a *keyword*.
Then, if a `((` is called "punctuation", that would mean that all compound commands (as (( is clearly one "compound command") should be called "punctuation", therefore: `if` and `case
16:51
@StéphaneChazelas
@StéphaneChazelas Yes, a (( is a word.

  last day (17 days later) »