<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>

CC BY-SA 4.0
2022-12-13T11:34:03.873Z
You could probably simplify your sed to `sed -n '/^>/{s/.*\[//; s/]//p}' file`.
terdon
CC BY-SA 4.0
2023-01-11T23:47:02.597Z
The `/^>/{` doesn't appear to be necessary.
Ed Morton
CC BY-SA 4.0
2022-12-12T15:49:15.667Z
2022-12-12T15:56:15.797Z
2022-12-12T15:56:15.797Z
Steve
<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>

CC BY-SA 4.0
2022-12-13T11:32:04.507Z
2022-12-13T11:32:04.507Z
terdon
<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>

CC BY-SA 4.0
2022-12-12T15:43:25.613Z
You could also pipe to sed, and skip the Perl dependency: `grep -o '\[[^]]*\]$' input.fa | sed 's/[][]//g'`
Steve
CC BY-SA 4.0
2022-12-13T11:13:10.183Z
@Steve what benefit would that give? You just added sed as a dependency instead. Both sed and perl are installed by default on the vast majority of systems, so unless you are using AIX or a very limited embedded system, perl is just as valid as sed.
terdon
CC BY-SA 4.0
2022-12-13T15:10:45.350Z
@terdon I agree, but nearly all systems with grep will have sed.
Steve
CC BY-SA 4.0
2022-12-13T16:03:41.897Z
@Steve yes, exactly like `perl`. Unless people are trying to do bioinformatics on toasters or something, I really don't see any point in using sed instead of perl. They are both very powerful, standard, ancient commands that have a long history in the *nix world in general and in bioinformatics in particular. The only full system (as opposed to embedded system) I know of that doesn't install perl by default is AIX and that isn't likely to be used for bioinformatics.
terdon
CC BY-SA 4.0
2022-12-13T18:38:11.717Z
Perl can easily be downloaded @Steve ;), "Dockerised", or "conda-ised". Not many Linux OS have removed Perl, `FreeBSD` is one. Most of us work with `Ubuntu`, `Debian` or `Darwin`. I think even Alpine Linux has Perl.
M__
CC BY-SA 4.0
2022-12-14T02:12:07.800Z
@terdon Well, Perl is a sed-killer. For simple substitutions like the above, PCRE are not needed. You can use Perl if you want to, but you _could_ also use sed and not need to escape the brackets.
Steve
CC BY-SA 4.0
2022-12-14T02:15:57.840Z
@M__ Alpine does not come with Perl out of the box
Steve
CC BY-SA 4.0
2022-12-14T10:54:57.900Z
@Steve well yes, but Alpine is mostly for embedded systems, right? Not sure what you mean about escaping, neither tool requires you to escape the brackets. And sure, of course you can use `sed`. I just don't see any benefit in using one external tool over another here. Nothing wrong with using sed, but nothing wrong with using perl either. Granted, if I bring out perl, I would probably do the whole thing in perl and remove the grep, but still.
terdon
CC BY-SA 4.0
2022-12-14T13:00:38.653Z
@Steve yes technically Alpine Linux holds `sed` and `grep` but via `Busybox` and its `grep` is basic without `-P`. I installed `perl` on Alpine it took a few seconds  maximum. However, the reason is the container is 7.5 MG and Alpine `Perl` is 55MB. The key to the question is `GNU` grep.
M__
CC BY-SA 4.0
2022-12-14T14:07:40.493Z
@terdon You're right, neither tool requires the brackets to be escaped but `'s/[[]]/ /g'` should be `'s/[][]/ /g` I think.
Steve
CC BY-SA 4.0
2022-12-14T14:35:55.677Z
@Steve eeeek! You're quite right, thanks!
terdon
CC BY-SA 4.0
2022-12-15T02:08:19.470Z
@Steve here's an article specially written for you ;) https://stackoverflow.blog/2022/07/06/why-perl-is-still-relevant-in-2022/
M__
CC BY-SA 4.0
2022-12-15T03:24:50.113Z
Thanks @M__ - I hadn't even heard of Perl 7 until now. But then I haven't really touched Perl for nearly a decade now. I just hope you're not confusing me for someone who dislikes Perl - that's certainly not the case. It's just that it's not needed here in my opinion. The Perl dependency also makes pipelining the solution tricky using the standard (i.e. non-mulled) quay.io biocontainers which provide the busybox suite. But that's not likely even a concern here..
Steve
CC BY-SA 4.0
2022-12-15T17:34:10.157Z
@Steve "not confusing me for someone who dislikes Perl " ... just checking ;) Fun as this is the last 3 comments at least need to be deleted, probably more
M__
CC BY-SA 4.0
2022-12-15T17:41:34.733Z
@terdon Alpine is a "freak" Linux OS, just for Docker containers. I should have checked my information before introducing it here :)
M__
CC BY-SA 4.0
2022-12-12T15:08:05.770Z
2022-12-14T14:36:21.067Z
2022-12-14T14:36:21.067Z
M__
<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>

CC BY-SA 4.0
2022-12-22T03:11:27.687Z
Thanks @Supertech perfect
M__
CC BY-SA 4.0
2022-12-22T01:34:15.903Z
2022-12-22T01:34:15.903Z
Supertech
<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>

CC BY-SA 4.0
2022-12-12T14:34:07.007Z
Is that _everything_ you have in the file? No other lines? And what operating system are you using?
terdon
CC BY-SA 4.0
2022-12-15T02:16:37.800Z
You can easily install GNU version of the commands into your Mac. Install the GNU Command Line Tools. You can do this using Homebrew, then
brew install coreutils. Default will be MacOS version (unless you intentionally set otherwise), but when you want to use GNU version, just add a "g" before the command. For example, "sort" vs "gsort"; "grep" vs "ggrep". It will make your life easier as a Mac user.
Supertech
<fasta><genome><grep>
Grep peculiar pattern inside a file
# Grep peculiar pattern inside a file

(Asked by: username_0 on 2022-12-12)

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

**Tags:** fasta, genome, grep
> **Comments:**
> **username_1**: Is that _everything_ you have in the file? No other lines? And what operating system are you using?  
> **username_2**: You can easily install GNU version of the commands into your Mac. Install the GNU Command Line Tools. You can do this using Homebrew, then brew install coreutils. Default will be MacOS version (unless you intentionally set otherwise), but when you want to use GNU version, just add a "g" before the command. For example, "sort" vs "gsort"; "grep" vs "ggrep". It will make your life easier as a Mac user.  

---

## 4 answers

### Answer by username_3 on 2022-12-12. Score: 4

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

> **Comments:**
> **username_1**: You could probably simplify your sed to `sed -n '/^>/{s/.*\[//; s/]//p}' file`.  
> **username_4**: The `/^>/{` doesn't appear to be necessary.  

---

### Answer by username_1 on 2022-12-13. Score: 3

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


---

### Answer by username_5 on 2022-12-12. Score: 2

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.

> **Comments:**
> **username_3**: You could also pipe to sed, and skip the Perl dependency: `grep -o '\[[^]]*\]$' input.fa | sed 's/[][]//g'`  
> **username_1**: @Steve what benefit would that give? You just added sed as a dependency instead. Both sed and perl are installed by default on the vast majority of systems, so unless you are using AIX or a very limited embedded system, perl is just as valid as sed.  
> **username_3**: @terdon I agree, but nearly all systems with grep will have sed.  
> **username_1**: @Steve yes, exactly like `perl`. Unless people are trying to do bioinformatics on toasters or something, I really don't see any point in using sed instead of perl. They are both very powerful, standard, ancient commands that have a long history in the *nix world in general and in bioinformatics in particular. The only full system (as opposed to embedded system) I know of that doesn't install perl by default is AIX and that isn't likely to be used for bioinformatics.  
> **username_5**: Perl can easily be downloaded @Steve ;), "Dockerised", or "conda-ised". Not many Linux OS have removed Perl, `FreeBSD` is one. Most of us work with `Ubuntu`, `Debian` or `Darwin`. I think even Alpine Linux has Perl.  
> **username_3**: @terdon Well, Perl is a sed-killer. For simple substitutions like the above, PCRE are not needed. You can use Perl if you want to, but you _could_ also use sed and not need to escape the brackets.  
> **username_3**: @M__ Alpine does not come with Perl out of the box  
> **username_1**: @Steve well yes, but Alpine is mostly for embedded systems, right? Not sure what you mean about escaping, neither tool requires you to escape the brackets. And sure, of course you can use `sed`. I just don't see any benefit in using one external tool over another here. Nothing wrong with using sed, but nothing wrong with using perl either. Granted, if I bring out perl, I would probably do the whole thing in perl and remove the grep, but still.  
> **username_5**: @Steve yes technically Alpine Linux holds `sed` and `grep` but via `Busybox` and its `grep` is basic without `-P`. I installed `perl` on Alpine it took a few seconds  maximum. However, the reason is the container is 7.5 MG and Alpine `Perl` is 55MB. The key to the question is `GNU` grep.  
> **username_3**: @terdon You're right, neither tool requires the brackets to be escaped but `'s/[[]]/ /g'` should be `'s/[][]/ /g` I think.  
> **username_1**: @Steve eeeek! You're quite right, thanks!  
> **username_5**: @Steve here's an article specially written for you ;) https://stackoverflow.blog/2022/07/06/why-perl-is-still-relevant-in-2022/  
> **username_3**: Thanks @M__ - I hadn't even heard of Perl 7 until now. But then I haven't really touched Perl for nearly a decade now. I just hope you're not confusing me for someone who dislikes Perl - that's certainly not the case. It's just that it's not needed here in my opinion. The Perl dependency also makes pipelining the solution tricky using the standard (i.e. non-mulled) quay.io biocontainers which provide the busybox suite. But that's not likely even a concern here..  
> **username_5**: @Steve "not confusing me for someone who dislikes Perl " ... just checking ;) Fun as this is the last 3 comments at least need to be deleted, probably more  
> **username_5**: @terdon Alpine is a "freak" Linux OS, just for Docker containers. I should have checked my information before introducing it here :)  

---

### Answer by username_2 on 2022-12-22. Score: 1

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`.

> **Comments:**
> **username_5**: Thanks @Supertech perfect  

---

