14

I am trying to count the number of lines after a problematic row in a csv file. I am aware I can use the grep -a # syntax to output # number of lines after a match has been found. I'm only interested in the actual number of lines. I realize I could set the number to MAX_INT, pipe it into a file and do some more processing.

I'm looking for a succinct one-liner to just tell me the count.

Any suggestions?

5 Answers 5

15
{ grep -m1 match; grep -c ''; } <file

That will work w/ GNU grep and an lseek()able infile. The first grep will stop at 1 -match, and the second will -count every line remaining in input.

Without GNU grep:

{ sed '/match/q'; grep -c ''; } <file

Of course, w/ grep you can use any/all of its other options besides, and stopping at one match is not at all necessary.

4
  • Both of these also print the line, and the second on prints up to the first match and then 0 for me ?
    – 123
    Jun 25, 2015 at 14:54
  • @User112638726 - you can drop the printout of the first match with grep -m1 match >/dev/null of course. And your second problem is a GNU sed - it doesn't reset its input offset per spec. You have to use -u w/ GNU - which is not always desirable. I could have been clearer, but my assumption was that a GNU grep and GNU sed would come in pairs. I think, also, grep -qm1 could work to shortcut the /dev/null redirect - but GNU grep does weird things w/ -q and i can't recall how those two work together.
    – mikeserv
    Jun 25, 2015 at 15:06
  • 1
    Nice answer - really demonstrates the power of command groupings. I don't know for sure, but I would guess wc -l is a little bit cheaper than grep -c ''. Jun 25, 2015 at 23:04
  • 1
    @DigitalTrauma - Yeah, i considered it (in retrospect), but I'd already written it, and it almost rhymed, so I figured I'd let well enough alone. And anyway, you said it too, so I'll sleep easy now.
    – mikeserv
    Jun 25, 2015 at 23:07
9

Here's one way.

$ cat foo
aaa
bbb
ccc
ddd
eee
fff
$ awk '/^ddd/{a=FNR}END{print FNR-a}' foo
2
$
3
  • 4
    this is not codegolf, can you give details ( FNR, END and so on) ?
    – Archemar
    Jun 25, 2015 at 14:23
  • 3
    Sure. awk uses FNR to identify the input record number. END is the code executed on reaching the end of the file. So when a match is found, the current record number is recorded. On reaching the end of the file, that number is then subtracted from the total number of lines in the file.
    – steve
    Jun 25, 2015 at 14:26
  • 1
    May aswell just use NR as it is one file.
    – 123
    Jun 25, 2015 at 14:36
6

Another way - use of dc is a little esoteric, but seems to work nicely here:

sed -n '/problem/=;$=' prob.txt | dc -e '??r-p'

sed searches prob.txt for "problem" and the last line, and uses the = command to output the line number of both.

dc reads these two values onto the stack, reverses them, subracts and prints the difference.

5

Entirely with sed(albeit two command with a pipe)

sed '/ddd/,$!d' file | sed -n '$='

Deletes all the line before the line and then the next command counts the lines in the new file.

3

This should delete all lines up to (and including) the problemtic one and then count the remaining lines:

sed '1,/problem/d' data.txt | wc -l
1
  • 1
    (assuming "problem" is not on the first line) Nov 10, 2015 at 15:07

You must log in to answer this question.

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