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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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