1
$\begingroup$

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

$\endgroup$
2
  • $\begingroup$ Is that everything you have in the file? No other lines? And what operating system are you using? $\endgroup$
    – terdon
    Dec 12, 2022 at 14:34
  • 1
    $\begingroup$ 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. $\endgroup$
    – Supertech
    Dec 15, 2022 at 2:16

4 Answers 4

4
$\begingroup$

One way using :

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
$\endgroup$
2
  • $\begingroup$ You could probably simplify your sed to sed -n '/^>/{s/.*\[//; s/]//p}' file. $\endgroup$
    – terdon
    Dec 13, 2022 at 11:34
  • $\begingroup$ The /^>/{ doesn't appear to be necessary. $\endgroup$
    – Ed Morton
    Jan 11 at 23:47
3
$\begingroup$

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
$\endgroup$
2
$\begingroup$

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.

$\endgroup$
15
  • $\begingroup$ You could also pipe to sed, and skip the Perl dependency: grep -o '\[[^]]*\]$' input.fa | sed 's/[][]//g' $\endgroup$
    – Steve
    Dec 12, 2022 at 15:43
  • $\begingroup$ @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. $\endgroup$
    – terdon
    Dec 13, 2022 at 11:13
  • $\begingroup$ @terdon I agree, but nearly all systems with grep will have sed. $\endgroup$
    – Steve
    Dec 13, 2022 at 15:10
  • $\begingroup$ @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. $\endgroup$
    – terdon
    Dec 13, 2022 at 16:03
  • 1
    $\begingroup$ 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.. $\endgroup$
    – Steve
    Dec 15, 2022 at 3:24
1
$\begingroup$

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.

$\endgroup$
1
  • 1
    $\begingroup$ Thanks @Supertech perfect $\endgroup$
    – M__
    Dec 22, 2022 at 3:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.