Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Command substitution vs process substitution

I am trying to understand the differences between these two similar commands.

aa=$(foo | bar | head -1)
read aa < <(foo | bar | head -1)
  • I know that <() requires #!/bin/bash, but does that make it slower?
  • Do they create the same amount of subshells?
  • Do they require the same amount of bash or sh processes?

I am looking to use the command with the best performance.

like image 978
Zombo Avatar asked Mar 14 '13 17:03

Zombo


People also ask

How does process substitution work?

In computing, process substitution is a form of inter-process communication that allows the input or output of a command to appear as a file. The command is substituted in-line, where a file name would normally occur, by the command shell.

What is command substitution explain with an example?

This command takes a line from standard input (usually your keyboard) and assigns consecutive words on that line to any variables named. For example: read first init last takes an input line of the form: J. Q. Public and has the same effect as if you had typed: first=J. init=Q. last=Public.

What is meant by the term command substitution '?

Command substitution is a mechanism that is followed by programmers in a shell script. In this mechanism, the output of a command replaces the command itself. Shell operates the expansion by executing a command and then replacing the command substitution with the standard output of the command.

Which command is used for command substitution?

The command substitution $(cat file ) can be replaced by the equivalent but faster $(< file ) . When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by ' $ ', ' ` ', or ' \ '.


1 Answers

  1. No. Bash is faster in non-POSIX mode.
  2. It depends. This is both an implementation-specific and platform-specific detail.
    • In Bash, both require the same number of processes. If lastpipe is not enabled, there is a process for each pipeline element plus a subshell for either substitution plus the parent process.
    • In Bash, if lastpipe is enabled, the last element of the pipeline will exec without forking in both cases, still requiring the same number of processes.
    • In ksh93, both should require the same number of processes in this case, but if the last pipeline element were a builtin, it would run in the process of the parent for the command substitution, making it even faster.
    • In both Bash and ksh93, if the shell is compiled on a system that does not support /dev/fd/*, the shell will create named pipes for process substitutions instead. This likely affects performance.
  3. The previous bullet should go here perhaps. Note "subshell" doesn't necessarily imply a separate process, though in almost all shells, it does (with the exception of $(<...) in everything except Bash that supports it). In mksh and ksh93, there's also the ${ ;} style command substitution, but each shell implements this differently. In ksh93, it may or may not give a speedup. in mksh, probably not. mksh doesn't support process substitutions, and zsh doesn't support (and has no way of simulating) BASHPID, so I haven't looked into it.

There is nothing intrinsically faster about a command substitution than a process substitution in Bash, but the head is redundant in the case of read since you're only reading a single line there. As an aside, always use head -n ... -- -1 is not portable. Also, don't use read without -r unless you want the shell to mangle the input.

like image 76
ormaaj Avatar answered Sep 19 '22 01:09

ormaaj