How Does Bash Script Command Substitution Work

Bash: command substitution when reading from a file

To be clear, this is an extremely bad idea, and is not something you should ever actually do. However, it would look like:

while IFS= read -r line; do
eval "echo $line" ## DANGEROUS: Do not do this!
done

In terms of why it's a bad idea:

  • It's innately insecure. BashFAQ #48 goes into more details on that, but in short, if your data can run the date command, it can run any other command as well.
  • It's slow. $(date) starts a new copy of /usr/bin/date each time it's run. Using printf -v date '%(%a %b %d)T' -1 stores the date formatted the way you want in $date far faster.

Why does command substitution work in example 2 but not example 1?

In the first example, you're running the result of the evaluation in the $(). Right now, that result starts with Mon, so you'll get a command not found error. In the second, you're assigning the result to a variable. To see it immediately, you can do:

echo "$(date | sed -r 's/[ ]{2,}/ /gi')"

But you also don't need to evaluate an extra step at all:

date | sed -r 's/[ ]{2,}/ /gi'

I would also recommend checking out man date, because date has builtin formatting options.

Command substitution into pipe

list_all is a function that writes to standard output; as such, it can be used as the input to grep by itself.

filter_username() {
read -p "Enter filter: " filter
output=$(list_all | grep "^$filter")
echo "$output"
}

Note that you don't need command substitutions in either case if you are only going to immediately write the contents of output to standard output and do nothing else with it.

list_all () {
sort lastb.txt | tail +2 | head -n -2 | sort | uniq -f3 | tr -s " " | cut -d' ' -f1,3,5,6
}

filter_username () {
read -p "Enter filter: " filter
list_all | grep "^$filter"
}


Related Topics



Leave a reply



Submit