Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
syntax:basicgrammar [2012/11/15 13:33]
ormaaj Mess with this page a bit. Wrote a "commands" section. Some half-finished stuff.
syntax:basicgrammar [2019/04/01 21:45] (current)
ddebhw Fix a little typo.
Line 3: Line 3:
 {{keywords>​bash shell scripting grammar syntax language}} {{keywords>​bash shell scripting grammar syntax language}}
  
-The shell language is built upon a few basic **grammar rules**. ​This article presents a **somewhat ​theoretical view**, ​though some terminology is tweaked a bit in order to avoid discussing too many corner-cases and to present a model that fits with reality most of the time. Having a correct understanding of the basic grammar is extremely important in understanding ​the language.+Bash builds its features on top of a few basic **grammar rules**. ​The code you see everywhere, the code you use, is based on those rules. However, ​**this is a very theoretical view**, ​but if you're interested, it may help you understand why things look the way they look.
  
-===== Commands =====+If you don't know the commands used in the following examples, just trust the explanation.
  
-<wrap center round info 90%>In the shell**everything** ​is command!</wrap>+===== Simple Commands ===== 
 +Bash manual says: 
 +<code> 
 +A simple command is a sequence of optional variable assignments followed by blank-separated words and redirections,​ 
 +and terminated by a control operator. The first word specifies ​the command to be executedand is passed as argument 
 +zero.  The remaining words are passed as arguments to the invoked ​command
 +</code>
  
-Bash is fundamentally a **command oriented language**, and it is very pure in this senseJust as highly functional or object oriented languages derive most or sometimes all of their grammar from primitive notions of //​functions//​ or //objects// respectivelyBash and other POSIX compatible shells build upon the concept of a **command**. The smallest valid chunk of shell code is always a **command**,​ as is every valid line you can enter at a prompt without an error. Likewise, an entire program of thousands of lines can consist of a single (composite) command.+Sounds harder than it actually ​is. It is what you do daily. You enter simple commands with parameters, and the shell executes them.
  
-Problems ​can arise when attempting to draw too many analogies between constructs found in other languages and shell commands. ​These are some useful ways to look at what a command is.+Every complex Bash operation ​can be split into simple ​commands
 +<​code>​ 
 +ls 
 +ls > list.txt 
 +ls -l 
 +LC_ALL=C ls 
 +</​code>​
  
-  * Commands are somewhat like **functions** found in other languages in that they provide for control flow, code reuse, modularity, and have a "scope" ​of sorts to provide some degree of encapsulation. A command has what is called an **execution ​environment** which consists ​of a set of properties local to the command and inherited from the parent execution environmentAll ksh-like shells additionally support function local variables, though this isn'​t ​specified by POSIX and the details can vary drastically between shells.+The last one might not be familiar. That one simply adds "''​LC_ALL=C''​" to the environment of the ''​ls''​ programIt doesn'​t ​affect your current shell. This also works while calling functions, unless Bash runs in POSIX(r) mode (in which case it affects your current shell).
  
-  * Commands can also be thought of as analogous to **programs** or **processes**. This is where the idea of //command// diverges from common language constructs. Importantly,​ each command has its own **implicit I/O**Just like running ​UNIX program, every command has its own file descriptors inherited from some parent environment. The execution environment of a command ​can includefor examplea local set of environment variablestrapped signals, file descriptors,​ and positional parameters. A command may or may not execute in a subshell, in which case the command or commands really have their own execution environment by virtue of being a real independent UNIX process.+Every command has an exit codeIt'​s ​type of return status. The shell can catch it and act on it. Exit code range is from 0 to 255where 0 means successand the rest mean either something failed, or there is an issue to report back to the calling program.
  
-These are crude descriptions and some liberty is taken with the term //​[[http://​pubs.opengroup.org/​onlinepubs/​9699919799/​utilities/​V3_chap02.html#​tag_18_12 | execution environment]]//​. We can't get too specific about what a command ​really ​is because they encompass every construct in the language. Commands can be subdivided into **two main types**: ​**[[basicgrammar##​simple_commands ​| simple]]** and **[[basicgrammar##​compound_commands | compound]]**.+<wrap center round info 90%> 
 +The simple ​command ​construct ​is the **base** for all higher constructs. Everything you execute, from pipelines to functions, finally ends up in (many) simple commands. That's why Bash only has one method to [[syntax:​grammar:​parser_exec ​expand and execute a simple ​command]]. 
 +</​wrap>​
  
-==== Simple Commands ==== 
  
-The Bash manual says: +===== Pipelines ===== 
-<​code>​ +FIXME Missing an additional article about pipelines ​and pipelining
-A simple command is a sequence of optional variable assignments followed by blank-separated words and redirections,​ +
-and terminated by a control operator. The first word specifies the command to be executed, and is passed as argument +
-zero.  The remaining words are passed as  arguments to the invoked command. +
-</​code>​+
  
-A simple command can be any or all of the following:​ +''​[time [-p]] [ ! ] command ​[ | command2 ​... ]''​
-  * A list of zero or more **words**, which designate a **command name** and a list of **arguments**. +
-  * Zero or more simple or compound assignments separated by whitespace which must precede the word list. +
-  * Zero or more **[[syntax/​redirection | redirection operators]]**, which may appear anywhere within the command, but by convention are usually placed after the word list.+
  
-Sounds harder than it actually is. It is what you do day-to-dayYou enter simple commands with parameters and the shell executes them. Remember, there are only two things, //simple// and //​compound//​ commands. Almost everything that isn't a [[basicgrammar##​compound_commands |compound command]] ​is a simple command. Many of the more complex constructs in Bash can be broken down into simple commands.+**Don'​t get confused** about the name "​pipeline." ​It's a grammatic name for a constructSuch a pipeline ​isn'​t ​necessarily ​pair of commands where stdout/​stdin ​is connected via real pipe.
  
-Some examples+Pipelines are one or more [[basicgrammar##​simple_commands | simple commands]] (separated by the ''​|''​ symbol connects their input and output), for example
-__A (very ;-)) simple command__+<​code>​ls /etc | wc -l</​code>​ 
 +will execute ''​ls''​ on ''/​etc''​ and **pipe** the output to ''​wc'',​ which will count the lines generated by the ls command. The result is the number of directory entries in /etc. 
 + 
 +The last command in the pipeline will set the exit code for the pipeline. This exit code can be "​inverted"​ by prefixing an exclamation mark to the pipeline: An unsuccessful pipeline will exit "​successful"​ and vice versa. 
 +In this example, the commands in the if stanza will be executed if the pattern "​^root:"​ is **not** found in ''/​etc/​passwd'':​
 <​code>​ <​code>​
-echo "Hello world..."+if ! grep '​^root:'​ /​etc/​passwd;​ then 
 +  ​echo "No root user defined... eh?" 
 +fi
 </​code>​ </​code>​
 +Yes, this is also a pipeline (although there is no pipe!), because the **exclamation mark to invert the exit code** can only be used in a pipeline.
 +If ''​grep'''​s exit code is 1 (FALSE) (the text was not found), the leading ''​!''​ will "​invert"​ the exit code, and the shell sees (and acts on) exit code 0 (TRUE) and the ''​then''​ part of the ''​if''​ stanza is executed. One could say we checked for "''​not grep "​^root"​ /​etc/​passwd''"​.
  
-__All of the following are simple commands__ +The [[commands:​builtin:​set#​attributes | set option pipefail]] determines the behavior ​of how bash reports ​the exit code of a pipeline. If it's set, then the exit code (''​$?''​is the last command that exits with non zero status, if none fail, it's zero. If it's not set, then ''​$?''​ always holds the exit code of the last command ​(as explained above).
-<code>​x=5</​code+
-<​code>>​tmpfile</​code>​ +
-<​code>​{x}<"​$x"​ _=${x=<(echo moo)} <&0$(cat <&"​$x"​ >&2)</​code>​+
  
 +The shell option ''​[[internals:​shell_options#​lastpipe | lastpipe]]''​ will execute the last element in a pipeline construct in the current shell environment,​ i.e. not a subshell.
 +
 +There'​s also an array ''​PIPESTATUS[]''​ that is set after a foreground pipeline is executed. Each element of ''​PIPESTATUS[]''​ reports the exit code of the respective command in the pipeline. Note: (1) it's only for foreground pipe and (2) for higher level structure that is built up from a pipeline. Like list, ''​PIPESTATUS[]''​ holds the exit status of the last pipeline command executed.
 +
 +Another thing you can do with pipelines is log their execution time. Note that **''​time''​ is not a command**, it is part of the pipeline syntax:
 <​code>​ <​code>​
-ls +# time updatedb 
-ls > list.txt +real    3m21.288s 
-ls -l +user    0m3.114s 
-LC_ALL=C ls+sys     ​0m4.744s
 </​code>​ </​code>​
  
-The last one might not be familiar to you. That one simply adds "''​LC_ALL=C''"​ to the environment of the ''​ls''​-program. It doesn'​t affect your current shell. This also works while calling functions, unless Bash runs in POSIX(r) mode (then it affects your current shell). 
  
-Every command has a so-called exit code - it's a kind of return status. The shell can catch it and react on it. It goes from 0 to 255, where 0 means success, and the rest means any kind of failure or issue to report back to the caller.+===== Lists ===== 
 +FIXME Missing an additional article about list operators
  
-<wrap center round info 90%> +A list is a sequence of one or more [[basicgrammar#​pipelines ​pipelines]] separated by one of the operators '';'',​ ''&'',​ ''&&'',​ or ''​││'',​ and optionally terminated by one of '';'',​ ''&'',​ or ''​<newline>''​.
-The simple command construct ​is the **base** for all higher constructs. Everything you execute, form pipelines to functions, finally ends up in (many) simple commands. That's why Bash only has one method to [[syntax:​grammar:​parser_exec ​finally expand and execute a simple command]]+
-</wrap>+
  
-  ​http://pubs.opengroup.org/onlinepubs/​9699919799/​utilities/​V3_chap02.html#​tag_18_09_01+=> It's a group of **pipelines** separated or terminated by **tokens** that all have **different meanings** for Bash. 
 + 
 +Your whole Bash script technically is one big single list! 
 + 
 +^Operator^Description^ 
 +|''<​PIPELINE1>​ **<​newline>​** <​PIPELINE2>''​|Newlines completely separate pipelinesThe next pipeline is executed without any checks. (You enter a command and press ''<​RETURN>''​!)| 
 +|''<​PIPELINE1>​ **;** <​PIPELINE2>''​|The semicolon does what ''<​newline>''​ does: It separates the pipelines| 
 +|''<​PIPELINE>​ **&** <​PIPELINE>''​|The pipeline in front of the ''&''​ is executed **asynchronously** ("in the background"​). If a pipeline follows this, it is executed immediately after the async pipeline starts| 
 +|''<​PIPELINE1>​ **&&​** <​PIPELINE2>''​|''<​PIPELINE1>''​ is executed and **only** if its exit code was 0 (TRUE), then ''<​PIPELINE2>''​ is executed (AND-List)| 
 +|''<​PIPELINE1>​ **<​nowiki>​||<​/nowiki>​** <​PIPELINE2>''​|''<​PIPELINE1>''​ is executed and **only** if its exit code was **not** 0 (FALSE), then ''<​PIPELINE2>''​ is executed (OR-List)| 
 + 
 +**Note:** POSIX calls this construct a "​compound lists".
  
-==== Compound Commands ====+===== Compound Commands ​=====
  
 See also the [[syntax:​ccmd:​intro | list of compound commands]]. See also the [[syntax:​ccmd:​intro | list of compound commands]].
  
 There are two forms of compound commands: There are two forms of compound commands:
-  * forming ​a new syntax element using lists as "​body"​ +  * form a new syntax element using a list as "​body"​ 
-  * complete ​independant syntax elements +  * completly ​independant syntax elements 
-Basicallyit'​s ​everything else that's not described ​elsewhere ​in this article. Compound commands have the following characteristics:​+Essentially, everything else that's not described in this article. Compound commands have the following characteristics:​
   * they **begin** and **end** with a specific keyword or operator (e.g. ''​for ... done''​)   * they **begin** and **end** with a specific keyword or operator (e.g. ''​for ... done''​)
   * they can be redirected as a whole   * they can be redirected as a whole
  
-See the following table for a short overview (without ​details - really ​just a plain overview!):+See the following table for a short overview (no details - just an overview):
 ^Compound command syntax^Description^ ^Compound command syntax^Description^
 |''​( <​LIST>​ )''​|Execute ''<​LIST>''​ in an extra subshell => [[syntax:​ccmd:​grouping_subshell | article]]| |''​( <​LIST>​ )''​|Execute ''<​LIST>''​ in an extra subshell => [[syntax:​ccmd:​grouping_subshell | article]]|
Line 82: Line 107:
 |''​for <​NAME>​ in <​WORDS>​ ; do <​LIST>​ ; done''​|Executes ''<​LIST>''​ while setting the variable ''<​NAME>''​ to one of ''<​WORDS>''​ on every iteration (classic for-loop) => [[syntax:​ccmd:​classic_for | article]]| |''​for <​NAME>​ in <​WORDS>​ ; do <​LIST>​ ; done''​|Executes ''<​LIST>''​ while setting the variable ''<​NAME>''​ to one of ''<​WORDS>''​ on every iteration (classic for-loop) => [[syntax:​ccmd:​classic_for | article]]|
 |''​for <​nowiki>​((</​nowiki>​ <​EXPR1>​ ; <​EXPR2>​ ; <​EXPR3>​ )) ; do <​LIST>​ ; done''​|C-style for-loop (driven by arithmetic expressions) => [[syntax:​ccmd:​c_for | article]]| |''​for <​nowiki>​((</​nowiki>​ <​EXPR1>​ ; <​EXPR2>​ ; <​EXPR3>​ )) ; do <​LIST>​ ; done''​|C-style for-loop (driven by arithmetic expressions) => [[syntax:​ccmd:​c_for | article]]|
-|''​select <​NAME>​ in <​WORDS>​ ; do <​LIST>​ ; done''​|Providing ​simple menus => [[syntax:​ccmd:​user_select | article]]| +|''​select <​NAME>​ in <​WORDS>​ ; do <​LIST>​ ; done''​|Provides ​simple menus => [[syntax:​ccmd:​user_select | article]]| 
-|''​case <​WORD>​ in <​PATTERN>​) <​LIST>​ ;; ... esac''​|Decicions ​based on pattern matching - executing ''<​LIST>''​ on match => [[syntax:​ccmd:​case | article]]| +|''​case <​WORD>​ in <​PATTERN>​) <​LIST>​ ;; ... esac''​|Decisions ​based on pattern matching - executing ''<​LIST>''​ on match => [[syntax:​ccmd:​case | article]]| 
-|''​if <​LIST>​ ; then <​LIST>​ ; else <​LIST>​ ; fi''​|The if-clause: ​making ​decisions based on exit codes => [[syntax:​ccmd:​if_clause | article]]|+|''​if <​LIST>​ ; then <​LIST>​ ; else <​LIST>​ ; fi''​|The if clause: ​makes decisions based on exit codes => [[syntax:​ccmd:​if_clause | article]]|
 |''​while <​LIST1>​ ; do <​LIST2>​ ; done''​|Execute ''<​LIST2>''​ while ''<​LIST1>''​ returns TRUE (exit code) => [[syntax:​ccmd:​while_loop | article]]| |''​while <​LIST1>​ ; do <​LIST2>​ ; done''​|Execute ''<​LIST2>''​ while ''<​LIST1>''​ returns TRUE (exit code) => [[syntax:​ccmd:​while_loop | article]]|
 |''​until <​LIST1>​ ; do <​LIST2>​ ; done''​|Execute ''<​LIST2>''​ until ''<​LIST1>''​ returns TRUE (exit code) => [[syntax:​ccmd:​until_loop | article]]| |''​until <​LIST1>​ ; do <​LIST2>​ ; done''​|Execute ''<​LIST2>''​ until ''<​LIST1>''​ returns TRUE (exit code) => [[syntax:​ccmd:​until_loop | article]]|
  
-=== Function Definition Command === 
-FIXME Missing an additional extra article about shell functions 
  
-A shell function definition basically makes a [[basicgrammar#​compound_commands | compound command]] available under a new name. The speciality now is, that function, when ran, has its own "​private"​ set of positional parameters and I/O descriptors. It acts like a script in the script. Simple said: **You create a new command.** 
  
-The definition is easy (one of more possibilities):​+ 
 +===== Shell Function Definitions ===== 
 +FIXME Missing an additional article about shell functions 
 + 
 +A shell function definition makes a [[basicgrammar#​compound_commands | compound command]] available via a new name. When the function runs, it has its own "​private"​ set of positional parameters and I/O descriptors. It acts like a script-within-the-script. Simply stated: **You'​ve created a new command.** 
 + 
 +The definition is easy (one of many possibilities):​
  
 ''<​NAME>​ () <​COMPOUND_COMMAND>​ <​REDIRECTIONS>''​ ''<​NAME>​ () <​COMPOUND_COMMAND>​ <​REDIRECTIONS>''​
  
-which usually ​is used with the ''​{...;​ }''​ compound command, and thus looks like+which is usually ​used with the ''​{...;​ }''​ compound command, and thus looks like:
 <​code>​ <​code>​
 print_help() { echo "​Sorry,​ no help available";​ } print_help() { echo "​Sorry,​ no help available";​ }
 </​code>​ </​code>​
  
-Like told above, a function definition can have any [[basicgrammar#​compound_commands | compound command]] as body. Structures like+As above, a function definition can have any [[basicgrammar#​compound_commands | compound command]] as body. Structures like
 <​code>​ <​code>​
 countme() for ((x=1;​x<​=9;​x++));​ do echo $x; done countme() for ((x=1;​x<​=9;​x++));​ do echo $x; done
 </​code>​ </​code>​
-are unusual, but perfectly valid since the for-loop construct is a compound command!+are unusual, but perfectly validsince the for loop construct is a compound command!
  
-If there are **redirections** specified, ​these are not performed ​on function ​definition, they are performed ​on function ​execution:+If **redirection** is specified, ​the redirection is not performed ​when the function ​is defined. It is performed ​when the function ​runs:
 <​code>​ <​code>​
-# this will NOT perform the redirection (on definition time)+# this will NOT perform the redirection (at definition time)
 f() { echo ok ; } > file f() { echo ok ; } > file
  
Line 124: Line 152:
 </​code>​ </​code>​
  
-The space between ''​NAME''​ and ''​()''​ is optional, usually you just see it without.+The space between ''​NAME''​ and ''​()''​ is optional, usually you see it without ​the space.
  
-I suggest ​to use the first form. It's specified in POSIX and all Bourne-like shells seem to support it.+I suggest ​using the first form. It's specified in POSIX and all Bourne-like shells seem to support it.
  
-__**Note:​**__ Before version ''​2.05-alpha1'',​ Bash only recognized the definition using curly braces (''​name() { ... }''​), also, other shells allow the definition using **any** command (not only compound command set).+__**Note:​**__ Before version ''​2.05-alpha1'',​ Bash only recognized the definition using curly braces (''​name() { ... }''​),​ other shells allow the definition using **any** command (not just the compound command set).
  
-To execute a function like a regular shell script you would put it together like this:+To execute a function like a regular shell script you put it together like this:
  
 <​code>​ <​code>​
Line 138: Line 166:
 mycmd() mycmd()
 { {
-  # this $1 is the one of the function!+  # this $1 belongs to the function!
   find / -iname "​$1"​   find / -iname "​$1"​
 } }
  
-# this $1 is the one of the script itself!+# this $1 belongs ​the script itself!
 mycmd "​$1"​ # Execute command immediately after defining function ​ mycmd "​$1"​ # Execute command immediately after defining function ​
  
Line 150: Line 178:
 **Just informational(1):​** **Just informational(1):​**
  
-Internally, for forking, Bash stores ​the function definitions in environment variables. Variables with the content "//() ....//"​.+Internally, for forking, Bash stores function definitions in environment variables. Variables with the content "//() ....//"​.
  
-Something ​like the following works without "​officially"​ declaring a function:+Something ​similar to the following works without "​officially"​ declaring a function:
 <​code>​ <​code>​
 $ export testfn="​() { echo test; }" $ export testfn="​() { echo test; }"
Line 162: Line 190:
 **Just informational(2):​** **Just informational(2):​**
  
-It is possible to set function names containing slashes:+It is possible to create ​function names containing slashes:
  
 <​code>​ <​code>​
Line 170: Line 198:
 </​code>​ </​code>​
  
-The elements of this name aren't subject to path search, of course.+The elements of this name aren't subject to path search.
  
-The weird names a function ​can have should not be used. Quote from the maintainer:+Weird function ​names should not be used. Quote from the maintainer:
   * //   * //
 It was a mistake to allow such characters in function names (`unset'​ doesn'​t It was a mistake to allow such characters in function names (`unset'​ doesn'​t
Line 178: Line 206:
 for backwards compatibility,​ but I don't have to encourage their use. for backwards compatibility,​ but I don't have to encourage their use.
 // //
- 
-  * http://​pubs.opengroup.org/​onlinepubs/​9699919799/​utilities/​V3_chap02.html#​tag_18_09_05 
- 
-===== Pipelines ===== 
-FIXME Missing an additional extra article about pipelines and pipelining 
- 
-''​[time [-p]] [ ! ] command [ | command2 ... ]''​ 
- 
-**Don'​t get confused** about the name "​pipeline"​ here, it's a grammar name for that construct, such a pipeline isn't necessarily a pair of commands where stdout/​stdin is connected through a real pipe. 
- 
-Basically, pipelines are one or more [[basicgrammar##​simple_commands | simple commands]] (when more, separated by the ''​|''​-symbol and connecting their input and output), for example: 
-<​code>​ls /etc | wc -l</​code>​ 
-will execute ''​ls''​ on ''/​etc''​ and **pipe** the output to ''​wc'',​ which will count lines. That way, you simply count your directory entries in /etc. 
- 
-The last command in the pipeline will also set the exit code for the pipeline. This exit code can be "​reversed"​ by preceeding an exclamation-mark to the pipeline: An unsuccessful pipeline will end up "​successful"​ and vice versa. 
-In this example, the commands in the if-structure will be executed, if the pattern "​^root:"​ is **not** found in ''/​etc/​passwd'':​ 
-<​code>​ 
-if ! grep '​^root:'​ /​etc/​passwd;​ then 
-  echo "No root-user defined... eh?" 
-fi 
-</​code>​ 
-Yes, this is also a pipeline (though there is no piping!), because the **exclamation mark to reverse the exit code** can only be used in pipelines. 
-If ''​grep'''​s exit code is 1 (FALSE) (the text was not found), the leading ''​!''​ will "​reverse"​ the exit code for the shell, the shell sees (and reacts on) exit code 0 (TRUE) and the ''​then''​-path of the ''​if''​-clause is executed. One could say we checked for "''​not grep "​^root"​ /​etc/​passwd''"​. 
- 
-The [[commands:​builtin:​set#​attributes | set option pipefail]] determines the behavior of how bash reports exit code of pipeline. If it's set, then the exit code (''​$?''​) is the last command that exits with non-0 status, if none fails, it's 0. If it's not set, then ''​$?''​ always holds the exit code of the last command (as explained above). 
- 
-The shell option ''​[[internals:​shell_options#​lastpipe | lastpipe]]''​ will make the last element in a pipeline construct being executed in the current shell environment,​ not in a separate subshell. 
- 
-There'​s also an array ''​PIPESTATUS[]''​ that is set after a foreground pipeline is executed. Each element of ''​PIPESTATUS[]''​ reports the exit code of each respective command in the pipeline. Note: (1) it's only for foreground pipe and (2) for higher level structure that is built up from pipeline, like list, ''​PIPESTATUS[]''​ holds only the last pipeline executed. 
- 
-Another thing you can do with pipelines is logging their execution time. Note that **''​time''​ is not a command**, it belongs to the special words for pipeline-syntax:​ 
-<​code>​ 
-# time updatedb 
-real    3m21.288s 
-user    0m3.114s 
-sys     ​0m4.744s 
-</​code>​ 
- 
-  * http://​pubs.opengroup.org/​onlinepubs/​9699919799/​utilities/​V3_chap02.html#​tag_18_09_02 
- 
-===== Lists ===== 
-FIXME Missing an additional extra article about the list operators 
- 
-A list is a sequence of one or more [[basicgrammar#​pipelines | pipelines]] separated by one of the operators '';'',​ ''&'',​ ''&&'',​ or ''​││'',​ and optionally terminated by one of '';'',​ ''&'',​ or ''<​newline>''​. 
- 
-=> It's a bunch of **pipelines** separated or terminated by **tokens** that all have **different meanings** for Bash. 
- 
-Your whole Bash script technically is one big single list! 
- 
-^Operator^Description^ 
-|''<​PIPELINE1>​ **<​newline>​** <​PIPELINE2>''​|Newlines completely separate pipelines. The next pipeline is simply executed, without any checks or specials (Hey! You do that every day! You enter a command and press ''<​RETURN>''​!)| 
-|''<​PIPELINE1>​ **;** <​PIPELINE2>''​|The semicolon does what ''<​newline>''​ does: It completely separates the pipelines| 
-|''<​PIPELINE>​ **&** <​PIPELINE>''​|The pipeline infront of that ''&''​ is executed **async** ("in background"​) - if a pipeline follows this, it is immediately executed after the async one was started| 
-|''<​PIPELINE1>​ **&&​** <​PIPELINE2>''​|''<​PIPELINE1>''​ is executed and **only** if its exit code was 0 (TRUE), then ''<​PIPELINE2>''​ is executed (AND-List)| 
-|''<​PIPELINE1>​ **<​nowiki>​||</​nowiki>​** <​PIPELINE2>''​|''<​PIPELINE1>''​ is executed and **only** if its exit code was **not** 0 (FALSE), then ''<​PIPELINE2>''​ is executed (OR-List)| 
- 
-**Note:** POSIX calls this construct a "​compound lists"​. 
- 
-  * http://​pubs.opengroup.org/​onlinepubs/​9699919799/​utilities/​V3_chap02.html#​tag_18_09_03 
  
  
 ===== Grammar summary ===== ===== Grammar summary =====
-Not much of correct definitions,​ just some short **slogans**:​ 
   * a [[basicgrammar#​simple_commands | simple command]] is just a command and its arguments   * a [[basicgrammar#​simple_commands | simple command]] is just a command and its arguments
   * a [[basicgrammar#​pipelines | pipeline]] is one or more [[basicgrammar#​simple_commands | simple command]] probably connected in a pipe   * a [[basicgrammar#​pipelines | pipeline]] is one or more [[basicgrammar#​simple_commands | simple command]] probably connected in a pipe
   * a [[basicgrammar#​lists | list]] is one or more [[basicgrammar#​pipelines | pipelines]] connected by special operators   * a [[basicgrammar#​lists | list]] is one or more [[basicgrammar#​pipelines | pipelines]] connected by special operators
   * a [[basicgrammar#​compound_commands | compound command]] is a [[basicgrammar#​lists | list]] or a special command that forms a new meta-command   * a [[basicgrammar#​compound_commands | compound command]] is a [[basicgrammar#​lists | list]] or a special command that forms a new meta-command
-  * a [[basicgrammar#​shell_function_definitions | function definition]] makes a [[basicgrammar#​compound_commands | compound command]] available under a new name, and in some kind of separate environment+  * a [[basicgrammar#​shell_function_definitions | function definition]] makes a [[basicgrammar#​compound_commands | compound command]] available under a new name, and separate environment
  
  
Line 253: Line 221:
  
 ---- ----
 +__A (very) simple command__
 +<​code>​
 +echo "Hello world..."​
 +</​code>​
  
 +__All of the following are simple commands__
 +<​code>​x=5</​code>​
 +<​code>>​tmpfile</​code>​
 +<​code>​{x}<"​$x"​ _=${x=<​(echo moo)} <&​0$(cat <&"​$x"​ >&​2)</​code>​
 ---- ----
 __A common compound command__ __A common compound command__
Line 261: Line 237:
 fi fi
 </​code>​ </​code>​
-  * the [[basicgrammar#​compound_commands | compound command]] for the ''​if''​-clause+  * the [[basicgrammar#​compound_commands | compound command]] for the ''​if''​ clause
   * the [[basicgrammar#​lists | list]] that ''​if''​ **checks** actually contains the [[basicgrammar#​simple_commands | simple command]] ''​[ -d /data/mp3 ]''​   * the [[basicgrammar#​lists | list]] that ''​if''​ **checks** actually contains the [[basicgrammar#​simple_commands | simple command]] ''​[ -d /data/mp3 ]''​
   * the [[basicgrammar#​lists | list]] that ''​if''​ **executes** contains a simple command (''​cp mymusic.mp3 /​data/​mp3''​)   * the [[basicgrammar#​lists | list]] that ''​if''​ **executes** contains a simple command (''​cp mymusic.mp3 /​data/​mp3''​)
  
  
-Let'​s ​reverse the exit code of the test command, only one thing changes:+Let'​s ​invert ​test command ​exit code, only one thing changes:
 <​code>​ <​code>​
 if ! [ -d /data/mp3 ]; then if ! [ -d /data/mp3 ]; then
Line 277: Line 253:
 ===== See also ===== ===== See also =====
  
-  * [[syntax:​ccmd:​intro | List of compound commands]] +  * Internal: ​[[syntax:​ccmd:​intro | List of compound commands]] 
-  * [[syntax:​grammar:​parser_exec | Parsing and execution of simple commands]] +  * Internal: ​[[syntax:​grammar:​parser_exec | Parsing and execution of simple commands]] 
-  * [[syntax:​quoting | Quoting and escaping]] +  * Internal: ​[[syntax:​quoting | Quoting and escaping]] 
-  * [[syntax:​expansion:​intro | Introduction to expansions and substitutions]] +  * Internal: ​[[syntax:​expansion:​intro | Introduction to expansions and substitutions]] 
-  * [[syntax:​words | Some words about words...]] +  * Internal: ​[[syntax:​words | Some words about words...]]
-  * [[http://​pubs.opengroup.org/​onlinepubs/​9699919799/​utilities/​V3_chap02.html#​tag_18_10 | shell grammar]]+
  
  • syntax/basicgrammar.1352986381.txt
  • Last modified: 2012/11/15 13:33
  • by ormaaj