Home > Software design >  Loop through table and parse multiple arguments to scripts in Bash
Loop through table and parse multiple arguments to scripts in Bash

Time:09-16

I am in a situation similar to this one and having difficulties implementing this kind of solution for my situation.

I have file.tsv formatted as follows:

x     y
dog     woof
CAT     meow
loud_goose     honk-honk
duck     quack

with a fixed number of columns (but variable rows) and I need to loop those pairs of values, all but the first one, in a script like the following (pseudocode)

for elements in list; do
    ./script1 elements[1] elements[2]
    ./script2 elements[1] elements[2]
done

so that script* can take the arguments from the pair and run with it.

Is there a way to do it in Bash?

I was thinking I could do something like this:

list1={`awk 'NR > 1{print $1}' file.tsv`}
list2={`awk 'NR > 1{print $2}' file.tsv`}

and then to call them in the loop based on their position, but I am not sure on how.

Thanks!

CodePudding user response:

Shell tables are not multi-dimensional so table element cannot store two arguments for your scripts. However since you are processing lines from file.tsv, you can iterate on each line, reading both elements at once like this:

#!/usr/bin/env sh

# Populate tab with a tab character
tab="$(printf '\t')"

# Since printf's sub-shell added a trailing newline, remove it
tab="${tab%?}"

{
  # Read first line in dummy variable _ to skip header
  read -r _

  # Iterate reading tab delimited x and y from each line
  while IFS="$tab" read -r x y || [ -n "$x" ]; do
    ./script1 "$x" "$y"
    ./script2 "$x" "$y"
  done
} < file.tsv # from this file

CodePudding user response:

You could try just a while read loop with the -a flag and IFS.

#!/usr/bin/env bash

while IFS=$' \t' read -ra line; do
  echo ./script1 "${line[0]}" "${line[1]}"
  echo ./script2 "${line[0]}" "${line[1]}"
done < <(tail -n  2 file.tsv)

Or without the tail

#!/usr/bin/env bash

skip=0 start=-1

while IFS=$' \t' read -ra line; do
  if ((start   >= skip)); then
    echo ./script1 "${line[0]}" "${line[1]}"
    echo ./script2 "${line[0]}" "${line[1]}"
  fi
done < file.tsv

  • Remove the echo's if you're satisfied with the output.
  • Related