@ Anatomy of the Command Line

SCaLE 14x
der.hans
Canonical

2016Jan23
16:30
Room 101




@ Caveats

. Skipping some pedantic details for sake of time
. Presume you're already familiar with shell features such as pipes, redirection, variable expansion.
. Going for the clearer examples rather than better code

@ ordering

. redirection
. pre-command variable assignment
. expansion
. pipes
. commands

@ redirection

. ripped from last week's headlines
echo "UseRoaming no" >> /etc/ssh/ssh_config
echo "UseRoaming no" | sudo tee -a /etc/ssh/ssh_config

echo anke >file.txt; grep anke file.txt
echo anke >file.txt; grep anke file.txt | grep anke >file.txt
echo anke >file.txt; ls -l file.txt; grep anke file.txt | grep anke | tee file.txt

echo -n $( echo foo >>file.txt ) >file.txt
echo $( echo foo >>file.txt; ls -l file.txt ) >file.txt

@ pre-command variable assignments

LANG=C
LANG=de_DE.UTF-8 find /ttmp | LANG=en_US sed -re 's/'

unset fred; fred=file.txt echo fred >$fred

@ expansion
. the 7 layer burrito of the command line
. 7 forms of expansion: brace  expansion, tilde  expansion,  parameter  and variable expansion, command substitution, arithmetic expansion, word splitting, and pathname expansion

@ expansion order
. brace expansion
. tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion)
. word splitting
. pathname expansion

@ bonus layer
. process substitution
.. evaluated at the same time as tilde, parameter, variable, and arithmetic expansion and command substitution

@ tokenizing
From the bash man page:
       Only brace expansion, word splitting, and pathname expansion can change
       the  number of words of the expansion; other expansions expand a single
       word to a single word.  The only exceptions to this are the  expansions
       of "$@" and "${name[@]}" as explained above (see PARAMETERS).

@ brace expansion 
. bashism, not in sh
. left to right order is preserved

echo {,/usr,${HOME}/local,/usr/local}/{,s}bin
echo {,/usr}/{,s}bin
echo {1..10}
ten=10; echo {1..$ten}
echo {1{0..9},20}
echo {a..e}
echo 1{0..9..2}

@ tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution 
. the squishy things, e.g. beans, cheese, salsa, guacamole, sriracha
. appear in the order encountered, might be intermixed

@ tilde expansion
. ls -ld ~/../../var/{lib,log,cache}
. ~+
. ~-
. dirs
. beware use in scripts

@ parameter expansion
. e.g. variables
. lots of fun string manipulation that can be done during parameter expansion
.. search the bash manpage for :-

@ command substitution and subshell
. copy of current env, not a brand new shell
. the turducken of burritos
. command substitution
.. replaces the command with the results of the command
.. $(command)
.. NOTE: do not use backticks
... backticks are not readable
... nesting with backticks is a quoting nightmare
. subshell
.. create a new env that doesn't change parent environment
.. ( cmd1; cmd2; cmd3 )
.. $( < $file ) is faster than $( cat $file )
. "If the substitution appears within double quotes, word splitting and pathname expansion are not performed on the results."

@ arithmetic expansion
echo $(( 3 + 1 ))
. integer only
echo $(( 3 + 1.5 ))
echo $(( 4 / 3 ))
. the expression is double quoted
. $[expression] syntax is deprecated
. nesting
echo $(( 3 + $(( 1 + 2 )) ))
. a double quote inside expression remains a double quote
. parameter and variable expansion, command substitution, and quote removal happen
( rush=2112; echo $(( 2 * $rush )) )
# ( orwell=$(( 1900 + 48 )); echo $orwell )
( cent=19; year=48; orwell=$(( $cent * 100 + $year )); echo $orwell )

@ process substitution
. system must support named pipes (FIFOs) or /dev/fd
ls -l <( echo anke ) # show /dev/fd
grep sources.list <(find /etc/ 2>/dev/null)
. useful for place where you need a file, but have stdout
ls -lR * >ls-lR.out
diff ls-lR.out <(ls -lR *)
( i=1984; while read i; do j=$(( ++i )); done < <( echo 2112 ); echo $j )

@ word splitting 
. splits on text not in double quotes
. IFS
ls $( echo /etc/resolv.conf /etc/issue )

@ pathname expansion
. globbing

@ quote removal

@ pipes 
. all commands fire up at the same time
find /ttmp | sed -re 's/'
sleep 2 | find /ttmp | sed -re 's/'
sleep 2 | find /ttmp | sed -re 's/' | ls -l /etc/issue

@ command
. the command or equivalent

@ functions, aliases
. e.g. commands

@ regex
. passed from shell to comand, but beware interpretation as globs
touch f.{1,2,3}.txt
echo fff >file.txt
grep f.* file.txt
echo f.* file.txt
grep f file.txt

@ further examples

(n05.txt; while read name; do count=$( grep -c "$name" $file ); echo $count $name; done < <(grep -E '^ [A-Z]* [A-Z]*$' $file | sort -u ) | sort -nr ) | less file=file.2016Jan05.txt; while read name; do count=$( grep -c "$name" $file ); echo $count $name; done < <(grep -E '^ [A-Z]* [A-Z]*$' $file | sort -u ) | sort -nr ) | less

@ resources
. bash man page
. Advanced Bash-Scripting Guide

@ 2016 der.hans CC BY-SA 4.0 Unported