Bash: Parameter Expansion (Substitution)

Bash Linux

Default Usage

${PARAMETER}

Expand parameter value. It can be used for:

  • Separating characters from variable names
    • cd /home/${user}
  • Positional parameter higher than 9
    • echo "Argument 10 is: ${10}"

Indirection

${!PARAMETER}

Expands to the value of the variable named by the value of parameter.

var=var1
var1=temp

$ echo ${!var}
temp

Case Modification

${PARAMETER^}, ${PARAMETER^^} ${PARAMETER,}, ${PARAMETER,,} ${PARAMETER~}, ${PARAMETER~~}

|Operator|Action| |–|————–| |^|Changes first character to upper case| |^^|Changes all characters to upper case| |,|Changes first character to lower case| |,,|Changes all characters to lower case| |~|Inverts case of first character| |~~|Inverts case of all characters|

Variable Name (Prefix) Expansion

${!PREFIX*} ${!PREFIX@}

Expands to a list of all set variable names beginning with the string in PREFIX.

$ echo ${!XDG*}
XDG_CURRENT_DESKTOP XDG_MENU_PREFIX XDG_RUNTIME_DIR XDG_SEAT XDG_SESSION_DESKTOP XDG_SESSION_ID XDG_SESSION_TYPE XDG_VTNR

Substring Removal

${PARAMETER#PATTERN} ${PARAMETER##PATTERN} ${PARAMETER%PATTERN} ${PARAMETER%%PATTERN}

With #, it removes the mathing pattern from the beggining of the variable, where # removes the shortest match, and ## removes the longest.

Note the empty spaces in the example below.

substr="the quick brown fox jumps over the lazy dog"

$ echo ${substr#* }
quick brown fox jumps over the lazy dog

$ echo ${substr##* }
dog

Removing path from a file:

mlog=/var/log/clamav/freshclam.log

$ echo ${mlog##*/}
freshclam.log

The operator % does the same, but at the end of the file.

$ echo ${substr% *}
the quick brown fox jumps over the lazy

$ echo ${substr%% *}
the

Changing the extension of a file

file=123.txt

$ echo ${file%.*}
123

$ echo ${file%.*}.log
123.log

Search and Replace

${PARAMETER/PATTERN/STRING} ${PARAMETER//PATTERN/STRING} ${PARAMETER/PATTERN} ${PARAMETER//PATTERN}

The main diffence is that a single / substitutes the first occurrence, while double // substitute all occurences:

$ echo $substr
the quick brown fox jumps over the lazy dog

$ echo ${substr/the/da}
da quick brown fox jumps over the lazy dog

$ echo ${substr//the/da}
da quick brown fox jumps over da lazy dog

$ echo ${substr/the}
quick brown fox jumps over the lazy dog

$ echo ${substr//the}
quick brown fox jumps over lazy dog

Anchoring

You can use # and % to anchor to the beginning and end respectively

var1=00000000

$ echo ${var1/#0/1}
10000000

$ echo ${var1/%0/1}
00000001

Offset and Lenght

${PARAMETER:OFFSET} ${PARAMETER:OFFSET:LENGTH}

  • Offset removes the amount of characters as specified
  • Lenght prints the specified character lenght after offset

Note: You can also use a negative value for offset and lenght, which will be calculated from the end of the file

$ echo ${substr}
the quick brown fox jumps over the lazy dog
123456789...

Removes first 9 chars

$ echo ${substr:9}
brown fox jumps over the lazy dog

Removes first 3 chars and print the next 5

$ echo ${substr:4:5}
quick

Use Default

${PARAMETER:-WORD} ${PARAMETER-WORD}

If parameter unset (or null if using :), expand to word.

$ my_var=gru
$ echo ${my_var:-yyz}
gru

$ unset my_var
$ echo ${my_var:-yyz}
yyz

Use Alternate Value

${PARAMETER:+WORD} ${PARAMETER+WORD}

If parameter is set (or null if using :), expand to word.

$ my_var=gru
$ echo ${my_var:+yyz}
yyz

$ unset my_var
$ echo ${my_var:+yyz}

Use Default And Assign

${PARAMETER:=WORD} ${PARAMETER=WORD}

If parameter unset (or null if using :), expand to word and assign parameter to the value of word.

my_var=gru

$ echo ${my_var:=yyz}
gru

$ unset my_var
$ echo ${my_var:=yyz}
yyz

$ echo $my_var
yyz

Display Error

${PARAMETER:?WORD} ${PARAMETER?WORD}

If parameter unset (or null if using :), display error with word as appendix, otherwise expand parameter.

my_var=gru

$ echo ${my_var:?Not set}
gru

$ unset my_var
$ echo ${my_var:?Not set}
bash: my_var: Not set

Reference:

Alternatives to Top

Linux Bash

Looking for alternatives to your usual top command? Here are some options.

htop

htop is based on ncurses and is compatible with most Linux (and Unix) systems. It’s also in most the official repos for most distros.

Features: - Mouse clicks (due to ncurses) - Defaults to multi-CPU view - Memory shown in GB

htop

Website: http://hisham.hm/htop/

vtop

vtop takes more of a graphical approach to top, while concentrating more on simplicity. It displays CPU and Memory usage live charts, as well as a running process list. It runs on Node.js and can be easily installed with npm install -g vtop.

Features: - Mouse clicks - Themes - Live chart (CPU, memory) - Process list

vtop

Website: https://github.com/MrRio/vtop

gtop

gtop takes the graphical interface of vtop to another level. Just like vtop, it also displays a live chart of both CPU and memory, however gtop adds a network live chart to the list, and pie charts for both memory and swap, as well as storage usage.

gtop also runs on Node.js, and can easily be installed with npm install gtop -g.

Features: - Live chart (CPU, memory/swap, network) - Pie chart (memory, swap, disk usage) - Process list

gtop

Website: https://github.com/aksakalli/gtop

s-tui

While s-tui is not a process monitoring utility, it displays great information about your process status. It’s python based and uses little resource. You can easily install it with sudo pip install s-tui.

Features: - Processor info - Live charts (CPU freq, utilization, temperature and power usage) - Built-in CPU stress testing

Website: https://amanusk.github.io/s-tui/

Bash - Command Substitution, Subshell and Codeblock

Bash Linux

Bash - Command Substitution, Subshell and Codeblock

Quick and simple differences between using $(..), (..) and {..;}.

  • $(command) or `command` - Command substitution (the output of a command replaces the command name) and is executed in a subshell. Please give preference to $(..) for better readability
  • ( command ) - Command list is executed in a subshell
  • { command ;} - Command list is executed in the current shell

Executing code

$ ( echo 123 )
123

$ $(echo 123) # this executes the output of the command
123: command not found

$ { echo 123 ;}
123

Fiding subshell level with built-in BASH_SUBSHELL variable

$ ( echo $BASH_SUBSHELL )
1
$ ( ( echo $BASH_SUBSHELL ) )
2

$ $($BASH_SUBSHELL)
1: command not found

$ { echo $BASH_SUBSHELL ;}
0

Passing variables to subshell

$ var1=1

$ ( echo $var1 )
1

$ $(echo $var1)
1: command not found

$ { echo $var1 ;}
1

Changing and getting variables values in subshell

$ var=1

$ ( var=2 ) ; echo $var
1

$ $(var=2) ; echo $var
1

# Because we did not create a subshell,
# variable is available to original shell
$ { var=2 ;} ; echo $var
2

Other usages

Example 1:

Multiple commands and multiple lines. This can be used with (..) and {..}.

$ { echo 1 ; echo 2 ; echo 3; }
1
2
3

$ {
> echo 1
> echo 2
> echo 3;
> }
1
2
3

Example 2:

Changing the environment for subshell with separate environment. Here, set -u is only set in the subshell, so only the first echo will error out.

unset var1 var2
(
  set -u
  echo $var2
)
echo $var1

Redirecting Bash Xtrace to a Separate Log

Linux Bash

So you have a Bash script that you want to troubleshoot, but you want to send stdout to a file, and stderr to another. Here’s a solution.

For example, I like to use Bash’s color to display failure or success on checks, and echo’s removal of new lines (echo -e "Wait for it...\c ") to wait for checks. For example, the screenshot below shows a script that check each step and report back.

terminal

Errors are displayed in red, and success in green, and this same output is sent to the stdout and to a log file as well.

Now I want to get error messages in a separate log file, so I can go back to my original log and match the time where it failed, with additional verbose from Bash’s xtrace.

The solution is very simple… I can just add the lines below to the top of my script:

# Debugging
debug_log="${HOME}/bin/log/script.debug"
exec 2>>${debug_log}
set -x

The first line setups my debug log, the second redirects stderr to my debug log, and the third enables xtrace (same as bash -x [script]).

Note that doing this will disable any errors from being show in stdout.

How to Record and Share a Terminal Session

Linux Shell

A while ago I had shared instructions on «How to Share a Terminal Window Online». This is great for live support.

Today I’m sharing instructions on how to record your teminal session, and not only share it, but also allow users to copy and paste text from the playback video.

The installation could not be easier. And to show how great this utility is, I’m showing the instructions using a «video» recorderd with «showterm».

Now go ahead and try copying text from the video. Isn’t that great!?


Reference:

http://showterm.io/

https://github.com/ConradIrwin/showterm

code with