0

I am trying to write a script that would count the number of columns in a file. However, I don't know what the name of the file will be. I am trying to create a file called tempfile which has the information from the argument catted into it.

Here is the script that I have so far for the script called columnCounter:

#!/bin/bash
read colNumber
count=0
for i in $colNumber
do
     count=`expr $count + 1'
done
echo "column number: $count"

The above code works as long as I have a file name with information and type it into the terminal in the following format: cat tempfile | columnCounter.

I tried adding the two lines of the below code to create a tempfile from the argument in the terminal and then cat the tempfile and pipe it to the columnCounter. But this does not work.

cat $1 > tempfile
cat tempfile | columnCounter
3
  • How does this count columns?
    – jesse_b
    Apr 18 '19 at 19:34
  • This seems like an X-Y problem. Is your final goal just to have a script that counts columns in a file?
    – jesse_b
    Apr 18 '19 at 19:35
  • Will the "columns" always be delimited by whitespace? What if the first line has less columns than another line? Do you only care about the first line?
    – jesse_b
    Apr 18 '19 at 19:48
1

In order to provide your filename as an argument to the script you need to use positional parameters

You could use the following script to accomplish this:

#!/bin/bash

awk '{ print NF; exit }' "$1"

This assumes you only care about the number of columns in the first line.


If you want to find the line with the highest number of columns you could do:

#!/bin/bash

awk 'NF > max { max = NF } END { print max }' "$1"

This will check the length of all lines in the file and print the longest


Now if you want to specify a delimiter you can use multiple positional parameters:

#!/bin/bash

delim=$1
file=$2

awk -F "$delim" 'NF > max { max = NF } END { print max }' "$file"

This will allow you to count the maximum column size in all sorts of files, like a csv:

./columnCounter , tempfile.csv

To get even more fancy we could use getopts to parse the arguments:

#!/bin/bash

while getopts d:f: opt; do
    case $opt in
        d)  delim=$OPTARG;;
        f)  file=$OPTARG;;
    esac
done

awk -F "$delim" 'NF > max { max = NF } END { print max }' "$file"

This would then be called like:

./columCounter -d , -f tempfile.csv
1
  • 1
    For the last variation, you could set file=/dev/stdin as a default value and also use awk ${delim+-F "$delim"} ... to use the default awk delimiter if no delimiter is given.
    – Kusalananda
    Apr 18 '19 at 20:10

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.