text: user15596: I would like to grep everything inside the second square bracket of a file:
  >AB1311658.1 unnamed protein product [C.sp. balc.]
  
  >evm.model.pilon.8 [actin][D.r.]
  
  >NP_0232343.1 [fucose mutarotase] [E.l.]
  
  Obtaining:
  C.sp. balc.
  
  D.r.
  
  E.l.
  
  How can I solve it?
  Marco
  
  user14180: Some of the solutions suggested above utilize GNU grep. If you are a Mac user, you can easily install GNU version of the commands into your Mac. You can do this by installing the GNU Command Line Tools. The easiest way is to use Homebrew, then brew install coreutils.
  The default commands will still be MacOS version (unless you intentionally set otherwise), but when you want to use GNU version, you could just add a g before the command. For example, sort vs gsort, grep vs ggrep. You can also check manual of the command the same way, e.g. man gsort. Trust me this will make your life easier as a Mac user.
  Also, in recent years default MacOS Terminal shell is zsh. If you desire you can switch it back to bash.
  
  user3848: For OSX, I don't have a -P option (Perl pattern matching) so the best I can do is finish the one-liner by piping into perl
  grep -o '\[.*\]\[[^]]*' input.fa | perl -p -e 's/[][]/ /g'
  
  The -o makes grep match the substring, rather than the entire line.
  With GNU grep (the default on Linux) and the -P option, it's a single line of grep where \K or (?=pattern), (?<=pattern) are used for non-capture characters and these are placed around the [
  grep -oP '(?<=\[).*(?=\]).*(?<=\[)[^]]*' input.fa
  
  The ?<= is a "positive lookbehind" and the ?= is a "positive lookahead".
  It's a lot easier to use a perl one-liner.
  
  user298: With GNU grep (the default on Linux):
  $ grep -oP '.*\[\K[^]]+' file
  C.sp. balc.
  D.r.
  E.l.
  
  The -o means "print only the matched portion of the line" and -P enables Perl Compatible Regular Expressions which give us \K for "ignore everything matched up to this point". So we then look for the longest possible string ending in a [ and discard it (.*\[\K), and then look for the longest possible stretch of non-] characters after that.
  For very large files, you can speed things up a little by focusing only on the header lines:
  grep -oP '^>.*\[\K[^]]+' file
  
  
  user10775: One way using sed:
  sed -n '/^>/s/.*\[\([^]]*\)\]$/\1/p' input.fa
  
  Results:
  C.sp. balc.
  D.r.
  E.l.
  
  Explanation:
  
  Turn off automatic printing of the pattern space using -n
  Address lines starting with a header using /^>/
  Perform a substitution using a capture group to select everything between the last set of brackets on these lines, with s/.*\[\([^]]*\)\]$/\1/
  Print the pattern space with p
  
  
original_text: 15596: <p>I would like to grep everything inside the second square bracket of a file:</p>
  <pre><code>&gt;AB1311658.1 unnamed protein product [C.sp. balc.]
  
  &gt;evm.model.pilon.8 [actin][D.r.]
  
  &gt;NP_0232343.1 [fucose mutarotase] [E.l.]
  </code></pre>
  <p>Obtaining:</p>
  <pre><code>C.sp. balc.
  
  D.r.
  
  E.l.
  </code></pre>
  <p>How can I solve it?</p>
  <p>Marco</p>
   14180: <p>Some of the solutions suggested above utilize GNU <code>grep.</code> If you are a Mac user, you can easily install GNU version of the commands into your Mac. You can do this by installing the GNU Command Line Tools. The easiest way is to use Homebrew, then <code>brew install coreutils.</code></p>
  <p>The default commands will still be MacOS version (unless you intentionally set otherwise), but when you want to use GNU version, you could just add a <code>g</code> before the command. For example, <code>sort</code> vs <code>gsort</code>, <code>grep</code> vs <code>ggrep</code>. You can also check manual of the command the same way, e.g. <code>man gsort</code>. Trust me this will make your life easier as a Mac user.</p>
  <p>Also, in recent years default MacOS Terminal shell is <code>zsh.</code> If you desire you can switch it back to <code>bash</code>.</p>
   3848: <p>For OSX, I don't have a <code>-P</code> option (Perl pattern matching) so the best I can do is finish the one-liner by piping into <code>perl</code></p>
  <pre><code>grep -o '\[.*\]\[[^]]*' input.fa | perl -p -e 's/[][]/ /g'
  </code></pre>
  <p>The <code>-o</code> makes <code>grep</code> match the substring, rather than the entire line.</p>
  <p>With GNU <code>grep</code> (the default on Linux) and the <code>-P</code> option, it's a single line of grep where <code>\K</code> or <code>(?=pattern)</code>, <code>(?&lt;=pattern)</code> are used for non-capture characters and these are placed around the <code>[</code></p>
  <pre><code>grep -oP '(?&lt;=\[).*(?=\]).*(?&lt;=\[)[^]]*' input.fa
  </code></pre>
  <p>The <code>?&lt;=</code> is a <a href="https://www.regextutorial.org/positive-and-negative-lookbehind-assertions.php" rel="nofollow noreferrer">&quot;positive lookbehind&quot;</a> and the <code>?=</code> is a <a href="https://www.regextutorial.org/positive-and-negative-lookahead-assertions.php" rel="nofollow noreferrer">&quot;positive lookahead&quot;</a>.</p>
  <p>It's a lot easier to use a <code>perl</code> one-liner.</p>
   298: <p>With GNU <code>grep</code> (the default on Linux):</p>
  <pre><code>$ grep -oP '.*\[\K[^]]+' file
  C.sp. balc.
  D.r.
  E.l.
  </code></pre>
  <p>The <code>-o</code> means &quot;print only the matched portion of the line&quot; and <code>-P</code> enables Perl Compatible Regular Expressions which give us <code>\K</code> for &quot;ignore everything matched up to this point&quot;. So we then look for the longest possible string ending in a <code>[</code> and discard it (<code>.*\[\K</code>), and then look for the longest possible stretch of non-<code>]</code> characters after that.</p>
  <p>For very large files, you can speed things up a little by focusing only on the header lines:</p>
  <pre><code>grep -oP '^&gt;.*\[\K[^]]+' file
  </code></pre>
   10775: <p>One way using <a href="/questions/tagged/sed" class="post-tag" title="show questions tagged &#39;sed&#39;" aria-label="show questions tagged &#39;sed&#39;" rel="tag" aria-labelledby="sed-container">sed</a>:</p>
  <pre><code>sed -n '/^&gt;/s/.*\[\([^]]*\)\]$/\1/p' input.fa
  </code></pre>
  <p>Results:</p>
  <pre><code>C.sp. balc.
  D.r.
  E.l.
  </code></pre>
  <p>Explanation:</p>
  <ul>
  <li>Turn off automatic printing of the pattern space using <code>-n</code></li>
  <li>Address lines starting with a header using <code>/^&gt;/</code></li>
  <li>Perform a substitution using a capture group to select everything between the last set of brackets on these lines, with <code>s/.*\[\([^]]*\)\]$/\1/</code></li>
  <li>Print the pattern space with <code>p</code></li>
  </ul>
  