Q1, Q2
What's the definition of a keyword?
Is "keyword" the same concept as "reserved word" in Bash Reference Manual?
Basically, special words important to the syntactic structure. In C there are goto
, if
, while
, enum
and so on; in bash you have if
, while
(these sound familiar..), time
, etc.
And yes, they are the same.
I am taking some liberty in interpreting the question, since the basic syntactic elements of POSIX shell and bash are similar. So let's look at the definition in POSIX.1:2013 Shell Command Language:
2.4 Reserved Words
Reserved words are words that have special meaning to the shell; see Shell Commands. The following words shall be recognized as reserved words:
...
This recognition shall only occur when none of the characters is quoted and when the word is used as:
...
See the grammar in Shell Grammar.
Let's take a look at the POSIX grammar to see how the Special Words—now syntatic tokens after lexing—in action:
for_clause : For name linebreak do_group
| For name linebreak in sequential_sep do_group
| For name linebreak in wordlist sequential_sep do_group
/* ... */
do_group : Do compound_list Done /* Apply rule 6 */
That looks familiar, right? Note that For
, Do
and Done
are really tokens that are supposed to be mapped and recognized by the lexer:
%token If Then Else Elif Fi Do Done
/* 'if' 'then' 'else' 'elif' 'fi' 'do' 'done' */
%token Case Esac While Until For
/* 'case' 'esac' 'while' 'until' 'for' */
/* and 'In' too -- They made a mistake! */
%token In /* 'in' */
If you have heard about Yacc or Bison (or well, jison), that's how people might use the grammar. With these parsers generators, they can generate something that figures out what parts of the grammar a given flow of input 'tokens' are spoken in.
Q3
Is a keyword necessarily not a command (or not a builtin command)?
As a keyword, is time
not a command (or not a builtin command)?
None of the keywords are treated like commands. But sure, you can have commands/functions with the same name, e.g.:
# make a command to avoid command-not-found for `FOO=BAR time cmd`
time(){ time "$@"; }
Based on the definitions of keyword and of builtin, why is time not a builtin but a keyword?
Because that's how people decided to make it:
// Licensed under GPLv2, bash:parse.y
// Copyright (C) 1989-2012 Free Software Foundation, Inc.
pipeline_command: pipeline
| BANG pipeline_command
| timespec pipeline_command
| timespec list_terminator
| BANG list_terminator;
pipeline : pipeline '|' newline_list pipeline
| pipeline BAR_AND newline_list pipeline
| command;
timespec : TIME | TIME TIMEOPT | TIME TIMEOPT TIMEIGN;
And they get extra power from this (see next question).
Q4
Why "you can do for instance time { foo; bar; }
" because "time
is a keyword"?
As a part of the grammar, people can naturally let the parser handle everything, and make decisions like allowing time
before compound commands. If time
was implemented as just a command, you will get a syntax error for constructs like such (try echo { foo; bar; }
), since it's really parsed with the 'usual' rules.
Also think about [[
. If [[
have not been a keyword, constructs like [[ ($a == 2) || ($b != 3) ]]
will make the shell find stray parentheses and complain. (Replace [[
with [
and see).
P.S. time
is a utility instead of a keyword in POSIX, although the latter is still considered acceptable. The whole time-a-trunk-of-commands thing is a ksh and bash extension.
[
builtin and[[
is a keyword? (Full titles over to the right under the heading "Linked".) – Wildcard Mar 05 '16 at 06:55