0

This may be a little trickier than the title implies. I basically want to iterate through an array of player names (which will be the table headers), and then list the teams associated with each player under them in two columns.

I've been successful using awk to create a single column table using the following code:

for ((i=0; i<${#PLAYERS[@]}; ++i)); do
    awk -F '\n' -v NAME="${PLAYERS[i]}" 'BEGIN {print "<tr>"; print "  <th colspan="2">" NAME "</th>"; print "</tr>"} \
    {print "<tr>"; for (j=1; j<=NF; j++) print "  <td>"$j"</td>"; print "</tr>"}' \
    < ${PLAYERS[i]}teams.list
done

The out of this is:

<tr>
  <th colspan=2>Player 1</th>
</tr>
<tr>
  <td>Team 1</td>
</tr>
<tr>
  <td>Team 2</td>
</tr>
<tr>
  <td>Team 3</td>
</tr>
<tr>
  <td>Team 4</td>
</tr>

(The rest of the HTML is generated elsewhere and is not relevant.)

What I want is this:

<tr>
  <th colspan=2>Player 1</th>
</tr>
<tr>
  <td>Team 1</td>
  <td>Team 2</td>
</tr>
<tr>
  <td>Team 3</td>
  <td>Team 4</td>
</tr>
1
  • reference $(j+1) for the 2nd value and increment loop by 2? Good luck. Commented Mar 10, 2016 at 4:06

2 Answers 2

1

Although it would certainly be possible to modify your existing code to accomplish this task, I chose to refactor it instead using methods I am a bit more familiar with than awk.

An added feature of the method I used is that an empty cell will be automatically added for players with an odd number of teams.

First, from your example, I assume you would have a file named "Player 1teams.list" with the follow text:

Team 1
Team 2
Team 3
Team 4

Here is my proposed solution, commented and optimized for readability:

#!/bin/bash

# Array of players
PLAYERS=("Player 1")

# Loop through players array
for PLAYER in "${PLAYERS[@]}"; do

    # Echo the table header row for the current player
    echo "<tr>"
    echo "  <th colspan=2>${PLAYER}</th>"
    echo "</tr>"

    # Reset the TEAMS array on each loop (reuse the array for each player)
    TEAMS=()

    # Read each line of the teams file for the current player
    while IFS= read -r LINE || [[ -n "$LINE" ]]; do
        # Store the current player's teams in an array
        TEAMS+=("$LINE")
    done < "${PLAYER}teams.list"

    # Calculate the array key for the last line of the file
    # (array keys are used for line numbers, so they start at 0 instead of 1)
    LASTLINE="$(( ${#TEAMS[@]} - 1 ))"

    # Loop through teams for the current player
    for LINE in "${!TEAMS[@]}"; do

        # If the current line number is even, we are starting a table row
        if [ "$(( LINE % 2 ))" -eq 0 ]; then
            echo "<tr>"
            echo "  <td>${TEAMS[$LINE]}</td>"

            # If an even line is the last line of the file, add a blank cell
            if [ "$LINE" == "$LASTLINE" ]; then
                echo "  <td></td>"
                echo "</tr>"
            fi

        # If the current line number is odd, we are ending a table row
        else
            echo "  <td>${TEAMS[$LINE]}</td>"
            echo "</tr>"
        fi
    done
done

Here is a condensed version of the the above code:

#!/bin/bash

# Array of players
PLAYERS=("Player 1")

for PLAYER in "${PLAYERS[@]}"; do
    echo -e "<tr>\n  <th colspan=2>${PLAYER}</th>\n</tr>"
    TEAMS=(); while IFS= read -r LINE || [[ -n "$LINE" ]]; do TEAMS+=("$LINE"); done < "${PLAYER}teams.list"
    LASTLINE="$(( ${#TEAMS[@]} - 1 ))"
    for LINE in "${!TEAMS[@]}"; do
        if [ "$(( LINE % 2 ))" -eq 0 ]; then
            echo -e "<tr>\n  <td>${TEAMS[$LINE]}</td>"
            if [ "$LINE" == "$LASTLINE" ]; then echo -e "  <td></td>\n</tr>"; fi
        else
            echo -e "  <td>${TEAMS[$LINE]}</td>\n</tr>"
        fi
    done
done

Edit: I have posted a new answer using the awk code you provided as well

Sign up to request clarification or add additional context in comments.

Comments

0

You can do this with an if statement which checks for even/odd numbered rows:

for ((i=0; i<${#PLAYERS[@]}; ++i)); do
    awk -F '\n' -v NAME="${PLAYERS[i]}" 'BEGIN {print "<tr>\n  <th colspan="2">" NAME "</th>\n</tr>"} \
    {if (NR%2==1) {print "<tr>\n  <td>"$0"</td>"} else {print "  <td>"$0"</td>\n</tr>"}}
    END {if (NR%2==1) {print "</tr>"}}' \
    "${PLAYERS[i]}teams.list"
done

The if statement checks that the current line is odd using the formula NR%2==1 (line number modulo 2 is equal to 1), then prints the appropriate html for that table row.

I also made the following code changes :

  • Removed the for loop, as awk already loops through each line of the file
  • Removed "<" file redirection, as awk already expects a filename as the last parameter
  • Joined multiple print statements using \n newline characters

Note: I posted this as a separate answer, as I had completely rewritten your code in my original post.

1 Comment

I like this, since I want to stick with awk. However, it isn't necessary to compensate for an odd number of teams. My program distributes teams evenly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.