How to get consolidated count of delimiter occurrence

Viewed 97

I have a requirement to fetch the count the occurrence of '|' in each line of a file then match the count with given inputcount, needs to throw exception when the count is wrong.

Say if the inputcount=3 and the file has following content

s01|test|aaa|hh
S02|test|bbb
so3|test|ccc|oo

then exception should get thrown on executing the line 2 and it should exit the file.

Tried below Awk command to fetch the count for each lines, but I was not sure how to compare and throw the exception, when it not matches

awk ' {print (split($0,a,"\|")-1) }' test.dat

Can anyone please help me with it?

4 Answers

You may use this awk:

awk -v inputcount=3 -F '\\|' 'NF && NF != inputcount+1 {exit 1}' file &&
 echo "good" || echo "bad"

Details:

  • -F '\\|' sets | as input field separator
  • NF != inputcount+1 will return true if any line doesn't have inputcount pipe delimiters.
$ inputcount=3
$ awk -v c="$inputcount" 'gsub(/\|/,"&")  !=  c{exit 1}' file
$ echo $?
1

Maybe try

awk -F '[|]' -v cols="$inputcount" 'NF != cols+1 {
    print FILENAME ":" FNR ":" $0 >"/dev/stderr"; exit 1 }' test.dat

The -F argument says to split on this delimiter; the number of resulting fields NF will be one more than there are delimiters, so we scream and die when that number is wrong.

As you also tagged the post with python I will write a python answer that could be a simple script.

The core is:

with open(filename) as f:
    for n, line in enumerate(f):
        if line.count("|") != 3:
            print(f"Not valid file at line {n + 1}")

Than you can add some boilerplate:

import fileinput
import sys

with fileinput.input() as f:
    for n, line in enumerate(f):
        if line.count("|") != 3:
            print(f"Not valid file at line {n + 1}")
            sys.exit(1)

And with fileinput you can accept almost any sort of input: see Piping to a python script from cmd shell

Related