0

Hello I have a file that looks like this:

ZC12A_MOUSE Mus musculus    Q5D1E7  PDB; 2N5J; NMR; -; A=45-89.
                    PDB; 2N5K; NMR; -; A=299-327.
                    PDB; 2N5L; NMR; -; A=544-596.
                    PDB; 5H9V; X-ray; 2.75 A; A/B/C/D=134-339.
                    PDB; 5H9W; X-ray; 2.60 A; A/B=134-339.

ZHX1_HUMAN  Homo sapiens    Q9UKY1  PDB; 2ECB; NMR; -; A=565-640.
                    PDB; 2GHF; NMR; -; A=60-153.
                    PDB; 2LY9; NMR; -; A=462-532.
                    PDB; 3NAR; X-ray; 2.60 A; A/B=655-731.

ZHX2_HUMAN  Homo sapiens    Q9Y6X8  PDB; 2DMP; NMR; -; A=524-599.
                    PDB; 3NAU; X-ray; 2.70 A; A/B=444-501.

I am trying to count the "blocks" in the file (here I have 3). So I can do this but counting the number of times it appears that in first column there is some letter/number? Is there some bash command that I could use?

3
  • You mean you want to count the number of the first word instances? eg ZHX1_HUMAN?
    – Oli
    Mar 5, 2018 at 9:44
  • no just the number of times in first columns something (letter or number) appears..so in this example its 3.
    – sergio
    Mar 5, 2018 at 9:47
  • Ah okay, I've covered a few bases :)
    – Oli
    Mar 5, 2018 at 9:51

3 Answers 3

1

It's easy to grab the lines that don't start with spaces with something like awk:

$ awk '/^\S/' test
ZC12A_MOUSE Mus musculus    Q5D1E7  PDB; 2N5J; NMR; -; A=45-89.
ZHX1_HUMAN  Homo sapiens    Q9UKY1  PDB; 2ECB; NMR; -; A=565-640.
ZHX2_HUMAN  Homo sapiens    Q9Y6X8  PDB; 2DMP; NMR; -; A=524-599.

If you just want to count that, you can pipe that into wc -l which counts lines from input:

$ awk '/^\S/' test | wc -l
3

You can also do more advanced things with awk —which is why I chose it— like separating out the first field from lines with no leading whitespace:

$ awk '/^\S/ {print $1}' test
ZC12A_MOUSE
ZHX1_HUMAN
ZHX2_HUMAN

And from there you can count unique instances of each of those. The only condition for that is you need to sort it first. Thankfully there are tools for all this stuff in the base install:

$ awk '/^\S/ {print $1}' test | sort | uniq -c
      1 ZC12A_MOUSE
      1 ZHX1_HUMAN
      1 ZHX2_HUMAN
0
1

You can use grep:

grep -c '^[[:alnum:]]' input-file

^ is start of the line, [[:alnum:]] matches alphabets or numbers (short for alphanumeric), and -c makes grep print the count.

2
  • 1
    \S (not whitespace) would work here too instead of [[:alnum:]]
    – Oli
    Mar 5, 2018 at 9:52
  • @Oli yes, possibly. Since OP said alphabets or numbers, I thought to play it safe.
    – Olorin
    Mar 5, 2018 at 9:53
1

If you're working with files that consist of multiline records, then you should familiarize yourself with awk's paragraph mode which is achieved by setting an empty record separator RS.

So for example to print the number of records (blocks) in your file you can simply unset RS and then print the number of records processed at the end:

awk -vRS= 'END {print NR}' file

If you want to print the first field of each multiline record that's simply

$ awk -vRS= '{print $1}' file
ZC12A_MOUSE
ZHX1_HUMAN
ZHX2_HUMAN

and so on - without having to resort to regular expression matching.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .