diff options
Diffstat (limited to 'content/post/mess with bash(2).md')
-rw-r--r-- | content/post/mess with bash(2).md | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/content/post/mess with bash(2).md b/content/post/mess with bash(2).md new file mode 100644 index 0000000..1e3b744 --- /dev/null +++ b/content/post/mess with bash(2).md @@ -0,0 +1,274 @@ ++++ +title = "Mess with Bash(2)" +date = 2022-09-29 +[taxonomies] +categories = ["code"] +tags = ["bash"] +[extra] +math = false ++++ +> More info is in this [tutorial](https://https://guide.bash.academy) + +> all value expansions (ie. all syntax with a `$` prefix) can only expand inside quoted arguments if the argument was *double-quoted* . Single quotes will turn the dollar-syntax into literal characters, causing bash to output the dollar rather than expand its value in-place! + +*"Value expansions (`$...`) must **always** be double-quoted."* + + +*Never leave a value expansion unquoted.* + + +## Redirection + +### File Redirection + +**0 is standard input, 1 is standard output, 2 is standard error** + +`[x] > file, [x] < file` + +Make ***File descriptor***(FD) `x` write to / read from file. + +> `echo hello > ~/World` +> +> `read line < ~/Word` +> +> `rm file 2>/dev/null` + +### File Descriptor copying + +`[x] >& y, [x] <& y` + +make FD `x` write to / read from FD `y`'s stream + +> the connection to the stream used by FD `y` is copied to FD `x` +> +> `curl cip.cc > result 2>&1` +> +> `ping localhost > result 2>&1` +> +> ```bash +> # exec can be used to change the file descriptors of bash itself, +> # and if you use an x that doesn't yet exist, +> # bash will create a new file descriptor ("plug") for you with that number. +> # - in command is to close new FD 3 we'd created before. +> # >&- is to close FD 1, <&- is to close FD0 +> exec 3>&1 >mylog; echo moo; exec 1>&3 3>&- +> ``` + +### Appending file redirection + +`[x] >> file` + +make FD `x` append to end of the file + +> A stream to `file` is opened for writing in append mode and is connected to file descriptor `x`. The regular file redirection operator `>` empties the file's contents when it opens the file so that only your bytes will be in the file. +> +> `echo hello >> ~/world` +> +> `echo world >> ~/world` + +### Redirecting standard output and standard error + +`&>file` + +Make both FD 1 (standard output) and FD 2 (standard error) write to file + +> This is a convenience operator which does the same thing as `>file 2>&1` but is more concise. Again, you can append rather than truncate by doubling the arrow: `&>>file` +> +> `ping localhost &>result` + +### Here documents + +```bash +<<delimiter + Here document +delimiter +``` + +Make FD 0 read from the string between `delimiter`s + +> Here-Documents are great for reading blocks of text to command line. +> +> ```bash +> cat << EOF +> this is within here document +> I can write as many lines as I like +> and terminate with line of demiliter only +> EOF //end of heredoc +> ``` + +### Here strings + +`<<< string` + +Make FD 0 read from the `string` + +> Here strings are very similar to here documents but more concise. They are generally preferred over here documents. +> +> ```bash +> cat <<< "This, +> is the here strings. tab will also be read." +> ``` + +### Moving file decipher + +`[x]>&y-, [x]<&y-` + +Replace FD `x` with FD `y` and close FD `y` + +> Easy way of `[x]>&y, y>&-` +> +> ```bash +> # 3>&1-: copy FD 1 to FD 3 and close FD 1. +> # >&3-: copy FD 3 to FD 1 and close FD 3. +> exec 3>&1- >mylog; echo moo; exec >&3- +> ``` + +### Reading and writing with file descriptor + +`[x] <> file` + +Open FD `x` for both reading and writing to `file` + +> The file descriptor at x is opened with a stream to the file that can be used for writing as well as reading bytes. Usually you'll use two file descriptors for this. **One of the rare cases where this is useful is when setting up a stream with a read/write device such as a network socket**. +> +> ```bash +> exec 5<>aFile +> cat >&5 "Hello world" # make FD 1 write to where FD 5 currently writing, copy file descriptor FD 5 to FD 1 +> cat <&5 # make FD 0 read from where FD 5 currently reading, copy file descriptor FD 5 to FD 0, then cat will send content to FD 1 +> ``` + +Exercise + +> Q: fix `exec 3>&2 2>log; echo 'Hello!'; exec 2>&3` so that the message is properly saved into the `log` file and such that FD 3 is properly closed afterwards: +> +> A: +> +> 1. `exec 3>&1- 3>log; echo 'Hello!'; exec 1>&3-` +> 2. `exec 3>&1 1>&- 3>log; echo 'Hello!'; exec 1>&3 3>&-` + +## Expansion + +### pathname expansion + +1. pattern expansion is performed by bash before command even execute + + > `file *` will show info about all file in current directory. `*` will expand to content before `file` execute. + > +2. A *glob* is the name of the type of pattern supported by the bash shell. + + > basic glob name supported by bash + > + >  + > + > **Those glob will only affect current directory, explicit expression is required to working on other directory.** `ls /sub/*` + > +3. extended glob can be enable to get more powerful but also easy confusing feature of bash + + > bash: `shopt -s extglob` + > zsh. : `setopt extendedglob` + >  + > + >  + > + +### Command Substitution + +we can expansion commands within commands, but must use double-quote `""` instead of `''` + +```bash +# this will output contents in hello.h to screen +cat hello.h + +# this will expand `cat hello.h` to real contents in +# file hello.h and concatenate to previous sentence +echo "file hello.h contains contents of $(cat hello.h)" + +# this will output 'file hello.h contains contents of $(cat hello.h)' +# without expand command in $() +echo 'file hello.h contains contents of $(cat hello.h)' +``` + +In command, `$()` is called *value expansion*, it consists of value-expansion prefix `$` and subshell `(...)`. A subshell is essentially a small new bash process that is used to run a command while the main bash shell waits for the result. + +## Parameters + +There are three kind of parameters: + +1. Environment Parameter +2. Positional Parameter +3. Variables + +### Environment Parameter + +environment variables exist at the process level. That means they are not a feature of the bash shell, but rather a feature of any program process on your system. They can inherit by children, but children's EV can't be given to parent. + +### Positional Parameter + +Just as name indicates, these kind of parameters indicate arguments' position, and always starting from 0. + +for example, imaging we have a script `rename`, arguments could be passed to it to extend its usage: + +`rename dir name` there, we passed `dir` and `name` as argument, so that positional parameters in script would be `$1` and `$2`, representing arguments respectively. after `$2`, such as `$3` is unset since there has no more argument. + +> Positional Parameter is read-only + +a new usage: `bash -c 'ls "$1"' -- '/home'`. This will working like `ls /home`, dash is necessary since it is first variable in shell we ran commands and it makes positional value of arguments populated after it stand as we expect in shell single-quoted command gonna run in. + +### Special Parameter + +Special parameters are parameters whose name is a single symbolic character, they are used to request certain state information from the bash shell. Like positional parameter, they are *read-only*. + + + +### Variables + +definition: `name=value` *//no space around `=` like other programming language support* + +call: like *command expansion*, using variable is to expand it with prefix `$`, e.g. `$name` + +* Keep in mind, Expansion should always be double-quoted * + +### Parameter expansion + +> [GNU material](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html) + +we expand parameters by prefixing their name with a `$` symbol + +> e.g. `name=me; echo hello "$name"`. `hello me`. + +In addition, we can put braces (`{` and `}`) around our parameter, which indicates where variable is about to begin and end. + +> e.g. `name=orange; echo there are 4 "${name}s"` `there are 4 oranges`. +> +> ```bash +> name=orange +> echo "there are 4 ${name}s." # there are 4 oranges. +> echo "there are 4 $names." # there are 4 . +> ``` +> +> here, we put `{}`around`name`so that bash can be told that suffix `s` is not a part of variable. otherwise, it will treat `names` as parameter and looking for its value, which is none in our example. + +parameter expansion brings up a powerful feature: *parameter expansion oerators* + +> While expanding a parameter, it is possible to apply an operator to the expanding value without alternate original value. +> +> I use these mostly +> +> ```bash +> # remove string before pattern ${name#pattern} shortest ${name##pattern} longest +> # remove string after pattern ${name%pattern} longest ${name%%pattern} shortest +> # delete first matching pattern ${name/pattern} +> # delete all matching pattern ${name//pattern} +> # substitute pattern with string ${name//pattern/string} +> +> foo="foo-bar-foobar" +> echo ${foo#*-} # echoes 'bar-foobar' (Removes 'foo-' because that matches '*-') +> echo ${foo##*-} # echoes 'foobar' (Removes 'foo-bar-') +> echo ${foo%-*} # echoes 'foo-bar' +> echo ${foo%%-*} # echoes 'foo' +> echo ${foo/-} # echoes 'foobar-foobar' +> echo ${foo//-} # echoes 'foobarfoobar' +> echo ${foo//-/_} # echoes 'foo_bar_foobar' +> ``` + + |