title: How to make a bash script to take input from command line (positionals), stdout (pipe), and process substitution?
body: <p>I wrote a script that takes a bunch of options (<code>-d</code>, <code>-v</code>, <code>-l</code>, as well as <code>--version</code>, <code>--leader</code>, etc...) and then the rest of the text (<code>$*</code>) can be anything. The script processes the text and spits it out reformatted. It's quite long, so here's a condensed version:</p>
  
  <pre class="lang-sh prettyprint-override"><code>## –––––––––––––––––––––––––[ myScript.sh ]–––––––––––––––––––––––––– ##
  
  # (1) Set up default values
  
  declare -- v='1.0' FS=$':\n\r\v\f\t'  Application='Finder' Files s='s'
  declare -i errors=0 element=0 counter=0 n L=2
  
  # (2) Parse user input
  until [[ -z "$1" || "$1" == '--' || "${1:0:1}" != '-' ]]; do
      [ "$Input" ] &amp;&amp; unset Input
      if [[ "$1" =~ ^(-[Ww]|--[Ww]idth=)([0-9]+)? ]]; then
          Input=$(echo "$1" | gsed -re 's|--?W(idth=)?||I' | grep -Eoe '^(0|[1-9][0-9]*)$')
          [ -z "$Input" ] &amp;&amp; echo "$2" | grep -Eoe '^(0|[1-9][0-9]*)$' &amp;&amp; Input="$2" &amp;&amp; shift 1
          (( Input &gt;= 0 )) &amp;&amp; Width="$Input" || unset Width
      elif [[ "$1" =~ ^((-[LlIi]|--(([Ll]ead(er|ing)?)?([Ii]n(dent)?)|[Ll]ead(er|ing)?)=)([0-9]+)?)$ ]]; then
          Input=$(echo "$1" | gsed -re 's|--?[a-z]+=?||I' | grep -Eoe '^(0|[1-9][0-9]*)$')
          [ -z "$Input" ] &amp;&amp; echo "$2" | grep -Eoe '^(0|[1-9][0-9]*)$' &amp;&amp; Input="$2" &amp;&amp; shift 1
          (( Input &gt;= 0 )) &amp;&amp; L="$Input" || unset L
      ...
      else printf "$(Bold 'Error:') Unrecognized option: '$(Tbrown "$1")'\n\n" &gt;&amp;2
          exit 2
      fi
      shift 1
  done
  
  #(3) Now here, get text
  IFS=''
  [ -n "${*}" ] &amp;&amp; declare Text="${*}" || Text="$(cat)" ## could also use read instead of cat ##
  [ -z "$Text" ] &amp;&amp; printf "$(Bold 'Error:') No text entered...\n\n" &gt;&amp;2 &amp;&amp; exit 2
  
  # (4) Process the text
  Text="$(echo "$Text" | gsed -rne '1h;1!H;$g;s|[\x0A-\x0D]+| |g;$p' | expand -t4 )"
  echo "$Text"    ##  (temporary)   ##
  exit 0          ##  (temporary)   ##
  ...             ## (process text) ##
  ...             ## (process more) ##
  </code></pre>
  
  <p>Part 3 works for accepting text as entered after options and when piped, but hangs waiting for input if no text is entered and doesn't see text passed as process substitution... eg:</p>
  
  <h3>Examples:</h3>
  
  <pre class="lang-sh prettyprint-override"><code>./myScript.sh -L10 --width=20 'This is a test'
  </code></pre>
  
  <p><code>&gt; This is a test
  </code></p>
  
  <pre class="lang-sh prettyprint-override"><code>echo 'This is a test' | ./myScript.sh -L10 --width=20
  </code></pre>
  
  <p><code>&gt; This is a test
  </code></p>
  
  <pre class="lang-sh prettyprint-override"><code>./myScript.sh -L10 --width=20 &lt; &lt;( echo 'This is a test' )
  </code></pre>
  
  <p><code>&gt; This is a test
  </code></p>
  
  <pre class="lang-sh prettyprint-override"><code>./myScript.sh -L10 --width=20       ##*** Want to stop this ***##
  </code></pre>
  
  <p><code>&gt; (No output)... hangs waiting on cat (or read) for a ^D
  </code></p>
  
  <pre class="lang-sh prettyprint-override"><code>echo 'This is a test' &gt;( ./myScript.sh )
  </code></pre>
  
  <p><code>&gt; This is a test /dev/fd/63</code>
  <code>&gt; &lt;B&gt;Error:&lt;/B&gt; No text entered...
  </code></p>
  
  <pre class="lang-sh prettyprint-override"><code>./myScript.sh -L10 --width=20 &lt;&lt;&lt;'This is a test'
  </code></pre>
  
  <p><code>&gt; This is a test
  </code></p>
  
  <pre class="lang-sh prettyprint-override"><code>echo "This is a test" | tee &gt;( ./myScript.sh -L10 --width=20 ) &gt;( ./myScript.sh  )
  </code></pre>
  
  <p><code>&gt; This is a test</code></p>
  
  <p><code>&gt; This is a test</code></p>
  
  <p><code>&gt; This is a test</code></p>
  
  <p>How do I get the script to not hang on cat or read, waiting for input? (withoout using timeout or read -t as that just slows things down)?</p>