I have tried:
grep -c "\|" *.*
But it didn't work, since it gives an incorrect count of consecutive pipes.
How can I accomplish this?
I have tried:
grep -c "\|" *.*
But it didn't work, since it gives an incorrect count of consecutive pipes.
How can I accomplish this?
You can use tr(1)
to delete all non-pipe characters and then use wc(1)
to get a total:
cat *.* | tr -d -c '|' | wc -c
Another option, using Perl, is:
perl -e 'while(<>){$c+=tr/|/|/};print "$c\n"' *
In non-one-liner format that's:
while(<>){
$c += tr/|/|/
}
print "$c\n"
The while(<>){
line is Perl magic for reading lines from files on the command or from STDIN
. You get used to it after a while. The line itself goes into a variable called $_
, which is the default parameter for many Perl commands. For instance tr
, which works quite a bit like tr(1)
, defaults to operating on $_
. I'm putting my results in a global variable called $c
. (In a full program, it's best to declare it a lexical variable with my $c = 0;
outside the loop.) The +=
operator adds the result of the tr
command (the number of pipe characters in this case) to the current value of $c
.
Just using tr(1)
is clearly a simpler option. ;-)
Using *.*
is a DOSism that you don't likely want to use on a UNIX-like platform.
Using single quotes to avoid having the shell interpret the pipe character reads a bit better. For instance, I tested my answer with:
$ echo '||||
|||||' | perl -e 'while(<>){$c+=tr/|/|/};print "$c\n"'
9
It's counterintuitive, but in most unix regex, escaping the |
makes it the or-operator. So your line is actually matching "nothing or nothing" (you can test this out by add some alternatives on either side). Just use
grep -c "|" *.*
Secondly, grep counts lines, not character occurrences. You could use a different tool; or, if you insist on grep, you could put each "|" on its own line. For example, with sed:
sed 's/|/|\n/g' *.*
Note: if using sed, I advise a lot of testing to make sure it does what you think it does. I needed to just then.
Finally, combine the ingredients:
cat *.* | sed 's/|/|\n/g' | grep -c "|"
Unfortunately this might not work for you, as you're probably not using unix (because of the *.*
). But hopefully it explains the problem, which I always find strangely reassuring.