title: Bash – conditional regex find/replace combined with converting customized %h%m%s format to seconds, single pass
body: <p>My input file will have the following format:  </p>
  
  <p><strong>input.txt</strong>:  </p>
  
  <pre><code>News A 1 B 2h 0m 1s C text1
  100 A 2 B 120m 1s C text2
  Show A 3 B 450s C text3
  Tom A 4 B 0:30 C text4
  Laura A 5 B 20 C text5
  Something A 6 B 1h 100m 70s C text6
  50 A 7 B 1h 10s C text7
  </code></pre>
  
  <p>(You see the weird time format at the 6th line, but that was intentional, just for demo, to simplify the logic without additional <code>0-59</code> requirement).  </p>
  
  <p>I want to apply the following regex to each line:  </p>
  
  <pre><code>^(.*?)A(.*?)B(.*?)C(.*?)$  
  </code></pre>
  
  <p>Note the syntax for <code>${BASH_REMATCH[3]}</code>. Valid variants:  </p>
  
  <ul>
  <li><code>\d{1,}h \d{1,}m \d{1,}s</code>  </li>
  <li><code>\d{1,}m \d{1,}s</code>  </li>
  <li><code>\d{1,}s</code>  </li>
  <li><code>\d{1,}</code> is equal to <code>\d{1,}s</code>  </li>
  </ul>
  
  <p>I need to convert this to seconds, but if this part fails to pass this validation, leave it as is. In any case, let's name the result <code>$sec</code>.  </p>
  
  <p>I'll need to define the following regex variables:  </p>
  
  <p><code>$price == '(\d{1,}) ', $names == '(Bob|Tom|Laura|Sandra) ', $tags == '(News|Show) '</code> (or <code>(?:regex)</code> syntax, I don't know which is better here)</p>
  
  <p>Then, replace the line with the following:  </p>
  
  <ul>
  <li><p>if <code>${BASH_REMATCH[1]} =~ $price</code>:  </p>
  
  <p><code>ID: ${BASH_REMATCH[2]}; time: $sec seconds; description: ${BASH_REMATCH[4]} – buy for " + "$" + ${BASH_REMATCH[1]}!</code> (I used <code>+</code> here to separate dollar signs) </p></li>
  <li><p>if <code>${BASH_REMATCH[1]} =~ $names</code>:  </p>
  
  <p><code>description: ${BASH_REMATCH[4]} from @${BASH_REMATCH[1]}; time: $sec seconds</code>  </p></li>
  <li><p>if <code>${BASH_REMATCH[1]} =~ $tags</code>:  </p>
  
  <p><code>ID: ${BASH_REMATCH[2]}; #${BASH_REMATCH[1]}; time: $sec seconds; description: ${BASH_REMATCH[4]}</code>  </p></li>
  <li><p>if <code>${BASH_REMATCH[1]}</code> doesn't match any predefined regex variable (or matches more than one variable):  </p>
  
  <p><code>ID: ${BASH_REMATCH[2]}; time: $sec seconds; ${BASH_REMATCH[1]}; description: ${BASH_REMATCH[4]}</code>  </p></li>
  </ul>
  
  <p>so the output file should be  </p>
  
  <p><strong>output.txt</strong>:  </p>
  
  <pre><code>ID: 1; #News; time: 7201 seconds; description: text1
  ID: 2; time: 7201 seconds; description: text2 – buy for $100!
  ID: 3; #Show; time: 450 seconds; description: text3
  description: text4 from @Tom; time: 0:30
  description: text5 from @Laura; time: 20 seconds
  ID: 6; time: 9670 seconds; Something; description: text6
  ID: 7; time: 1h 10s; description: text7 – buy for $50!
  </code></pre>
  
  <p>I want to use <strong>pure Bash</strong> if possible. By the way, I like the syntax used in these answers: <a href="https://stackoverflow.com/a/5659672/1736903">a/5659672/1736903</a> and <a href="https://stackoverflow.com/a/21507572">a/21507572</a>, but I don't know how to apply it to my situation.</p>