reading configuration files in bash. Best way?

Context:
I have a random pin number generator script that reads a tab-delimited file containing a location and a count:

eg.,

mansfield     30
tokyo          15
smithville     34

It produces random PIN# in the amount specified by the number in the second column.

Currently, I read the file and execute the generator function as follows:

while read line
do
    BRANCH=$(awk -F"\t" '{print $1}' <<< "$line")
    CNT=$(awk -F"\t" '{print $2}' <<< "$line")
    rand_pass "$BRANCH" $CNT
done < $file

I could also do something like this:

declare -a Array3
saveIFS="$IFS"
IFS=$'\n'
Array3=($(<$LIST))
IFS="$saveIFS"

Then:

for i in ${!Array3[@]}
do
    A=${Array3//[[:digit:][:space:]]/}
    B=${Array3//[[:alpha:][:space:]]/}
    rand_pass "$A" $B
done

Or ...I could source the file ....but ....

The script won't know the names or amount of parameters in the file.
The file will have stuff added to it over time.
I could chuck it into the script:

$ script.sh < file.txt

Then deal with the passed variables that way ...but why?
Is there a point or advantage to sourcing the file in this case?
Have I already arrived at the ideal ( or one of several ) solution?

Thanks for reading!

Bubnoff

while IFS=\<tab> read -r b c; do
    rand_pass "$b" "$c"
done < "$file"

Replace <tab> with an actual tab character, if, as your awk implies, the file's records contain tab-delimited fields.

Regards,
Alister

1 Like

Like this?

while IFS=$'\t' read -r b c

Is there a better way to indicate the value of IFS? I had
issues simply going:

IFS=\t

Thanks!

Bub

PS: It's working ...just wondering about the quoting.

$'\t' (which is equivalent to a single quoted tab) works fine, if your shell supports it. If not, a backslash followed by a literal tab character would also work. It's important that the tab be quoted (as in your dollar sign syntax, or with a backslash, or quotes), otherwise, assuming a default value of IFS (space, tab, newline), the shell would consume the tab during the field splitting and IFS would be set to a null string.

Typing a literal tab on the command line can be done by typing control-v followed by control-i, or control-v followed by the tab key. In a text editor, you may be able to simply type tab, depending on how it's configured. A simple \t would not work. To the shell, that's equivalent to a plain t.

Regards and thank you very much for the bits,
Alister

Awesome, thanks!

Are you sure you need to change the IFS?
Doesn't this work?

while read B C
do   rand_pass "$B" "$C"
done < "$file"

Using the default value of IFS (space, tab, newline) would fail if the branch name consists of more than one space-separated word. The first word would be assigned to b, and the rest of the city words plus the count would be assigned to c.

The original code uses a tab delimiter, so mine does as well.

Regards,
Alister

Some of the locations have two words ...east this, or grand that, blah-blah
city. The tab is essential. This is one reason I was asking about the possibilities for sourcing the file with some variation of:

LOC1=( "Grand Rapids" 16 )
LOC2=( "East Shanghai" 11 )

To my thinking, though, it seems like it would require more processing in
the script rather than less, and so I opted for the solution posted. The
script would have to handle an unknown amount of variables in the sourced file and be able to process them not knowing much about them:
quantity, naming conventions ...etc. The file would be added to, possibly by someone not knowing how the script works. The simple while loop/IFS solution is both readable and reliable. The person adding to the file simply needs to remember to tab between fields.

Thanks again!

Bub