0

I wrote the following bash script to print the top and bottom rows of a CSV file as a table.

#!/usr/bin/env bash   
                                                                                                            
# Default argument                                                                                          
num=10                                                                                                      
                                                                                                            
# Get flag values                                                                                           
while getopts ":n:" opt; do                                                                                 
   case $opt in                                                                                             
       n)                                                                                                   
           # Get argument values                                                                            
           num=$OPTARG                                                                                      
           # Print to check                                                                                 
           echo $num                                                                                        
           ;;                                                                                               
   esac                                                                                                     
done                                                                                                        
                                                                                                            
column -t -s , <(head -n $((num+1)) $1) <(tail -n $num $1)                                                  
                             

By default, I set the number of top and bottom rows to be shown at 10. The script runs fine without the -n flag. When I specify the flag, however, my echo shows that num has been set correctly, but I get the following errors:

tail: option requires an argument -- 'n'
Try 'tail --help' for more information.
head: option requires an argument -- 'n'
Try 'head --help' for more information.
                            

It seems that num isn't being seen by either tail or head. Even if I stick an echo right before that final command, I can see that num is set correctly, but clearly something is wrong. Why am I receiving these errors?

PS I use this CSV file for my testing.


Prompted by Cyrus' helpful advice, I get the following in debug mode (where ht is the name of my script):

./ht -n 5 sealevels.csv 
+ num=10
+ getopts :n: opt
+ case $opt in
+ num=5
+ echo 5
5
+ getopts :n: opt
+ echo 5
5
+ column -t -s , /dev/fd/63 /dev/fd/62
++ head -n 6 -n
++ tail -n 5 -n
head: option requires an argument -- 'n'
Try 'head --help' for more information.
tail: option requires an argument -- 'n'
Try 'tail --help' for more information.

Where is that extra trailing -n coming from?!

Dan
  • 11,370
  • 4
  • 43
  • 68
  • 1
    This might help: [How to debug a bash script?](http://unix.stackexchange.com/q/155551/74329) – Cyrus Apr 04 '21 at 02:56
  • 1
    So your `$1` is `-n`, not... whatever you expect it to be. Makes the issue pretty clear, right? So, what do you _want_ `$1` to be? – Charles Duffy Apr 04 '21 at 03:03
  • (Personally, I don't recommend using `getopts` at all; when using the practices described in [BashFAQ #35](https://mywiki.wooledge.org/BashFAQ/035), you're `shift`ing off all the arguments parsed as options explicitly, and it works consistently even on non-GNU platforms). – Charles Duffy Apr 04 '21 at 03:05
  • 2
    [What is a reason for using `shift $((OPTIND-1))` after `getopts`?](https://stackoverflow.com/questions/26294218/what-is-a-reason-for-using-shift-optind-1-after-getopts) – Charles Duffy Apr 04 '21 at 03:05
  • 2
    Not directly related to your problem, btw, but there are some quoting bugs here. Consider running your code through http://shellcheck.net/ and fixing what it finds. – Charles Duffy Apr 04 '21 at 03:08

0 Answers0