Romonov
Romonov

Reputation: 8605

bash shell script for reading a fields in a file and producing commands

I am new to bash shell scripting and would be thankful for suggestions of a script that can do this task. I have a file (list.cqt) with many lines. Each line has a list of fields separated by '/' in the following format: /Field1/Field2/Field3/Field4/Field5/Field6/Field7/Field8/Field9/Field10

For e.g. the contents in list.cqt are:
/F11/F12/F13/F14/F15/F16/F17/F18/F19/F110
/F21/F22/F23/F24/F25/F26/F27/F28/F29/F210
...
/Fx1/Fx2/Fx3/Fx4/Fx5/Fx6/Fx7/Fx8/Fx9/Fx10

(I modifyied the names inside each field just for simplifying the problem. Only the number of fields is constant in each line. Contents in each field can be anything - numbers, characters, etc)

I need to write a script to execute the following command by reading each line from list.cqt:
command arg1 arg2 arg3 arg4 *arg5* arg6 arg7 arg8 arg9 arg10

Only arg4, arg5, arg7 and arg10 change for each line read. Rest all remain the same.
arg4 is Field4 in that line in list.cqt
arg5 is Field6 in that line in list.cqt
arg7 basically starts with -1000 for the first command and changes in increments of 100. So for the second command it will be -900 for second command, so on, and 0 for 11th command, 100 for 12th command, 200 for 13th command etc.
arg10 is same absolute value as arg7 but with opposite sign. So if arg7 is -600, arg10 is 600. If arg7 is 400, arg10 is -400.

For example, reading the first two lines from list.cqt in the above example of the file, the commands will be:
command arg1 arg2 arg3 F14 F16 arg6 -1000 arg8 arg9 1000
command arg1 arg2 arg3 F24 F26 arg6 -900 arg8 arg9 900

Thank you!

Upvotes: 1

Views: 3212

Answers (2)

Igor Chubin
Igor Chubin

Reputation: 64573

I added echo before command because it's better to check if generated list is correct:

arg7=-1000
arg10=1000
while read line
do
  set $(echo $line | tr / ' ')
  echo command arg1 arg2 arg3 "$4" "$6" arg6 "$arg7" arg8 arg9 "$arg10"
  arg10=$((arg10-100))
  arg7=$((arg7+100))
done < list.cqt

If it is, just remove echo and run the script.

Here you process list.cqt line by line and set parts of its line to positional arguments of shell; then you use this parts as $4 and $6. Variables arg10 and arg7 are increased/decreased each time a line from the list.cqt file is processed.

Update

You can also use arrays instead of positional arguments (thanks to Dennis Williamson and kojiro for the tip):

arg7=-1000
arg10=1000
while IFS=/ read line
do
  echo command arg1 arg2 arg3 "${line[4]}" "${line[6]}" arg6 "$arg7" arg8 arg9 "$arg10"
  arg10=$((arg10-100))
  arg7=$((arg7+100))
done < list.cqt

That makes the code a little bit faster and cleaner.

Upvotes: 2

kojiro
kojiro

Reputation: 77137

You can control the delimiter of the shell's read command via the Internal Field Separator IFS. If you read into an array it's easy to access the indexed values. Then it becomes a simple matter of looping over the input and updating your counter variables. If you save the arguments to an array, you can just pass the expanded array as the arguments to your command.

#!/bin/bash

# Use set -x to see if the array "args" is getting assigned the values you expect.
IFS='/'
counter=-1000
while read -a fields; do
    (( counter+=100 ))
    args=(
        'arg1' 'arg2' 'arg3'
        "${fields[4]}" "${fields[6]}" 'arg6'
        $counter 'arg8' 'arg9' $(( -1 * counter ))
    )
    # command "${args[@]}"
done < list.cqt

Upvotes: 3

Related Questions