1

Here is the table...

Group   Name            Designation
2       (John)          Front End Developer
12      (Jim)           Back End Developer
8       (Jill)          Full Stack Developer
21      (Jack)          Front End Developer
2       (James)         Front End Developer
12      (Jane)          Full Stack Developer

I want to extract person names belong to same group. Here John and James belong to group 2. What (combination of) bash commands or script should I use to display the following output

John
James

I used different types of grep combinations. But doesn't seem to work.

3
  • Let's see the various combinations you tried. Jun 15, 2016 at 6:03
  • I tried this... grep -w "2" file.txt | awk '{print $2}' This printed names along with braces like this... (John) (James) I couldn't get rid of those parenthesis
    – NayabSD
    Jun 15, 2016 at 8:25
  • I've written a bash script that does all of this for you, and can be used on all kinds of tables being produced by commands. See: superuser.com/a/1756298/904602
    – Dan Bray
    Dec 5, 2022 at 19:40

2 Answers 2

0

You could use sed like this:

sed -n '/^2 /s/.*(\([^)]\+\)).*/\1/p' file.txt

Or awk like this:

awk -F "[()]" '/^2 / {print $2}' file.txt

The first solution replaces the line with the string enclosed in parentheses before printing it. The second solution uses parentheses as field separators and then only prints field two (the enclosed string).

2
  • Hi @Michael above both commands didn't produce any results. But I used this. grep -w "2" file.txt | awk -F "[()]" '{print $2}'. Worked fine. Thanks for the answer.
    – NayabSD
    Jun 15, 2016 at 13:07
  • Presumably, your file contains tabs instead of blanks, then. Jun 15, 2016 at 17:19
0

I've written a bash script to do this, but to work with all sorts of commands as inputs.

Here's the script:

#!/bin/bash

# Flags - to avoid potential conflicts when the labels are numbers
# 1st
# -n = only number for column
# -t = only text for column
# -a = any for column
# 2nd
# -n = only number for row
# -t = only text for row
# -a = any for row
nc=1; tc=1; nr=1; tr=1
if [ ${1:0:1} == "-" ]; then
    if [ ${1:1:1} == "n" ]; then
        tc=0
    elif [ ${1:1:1} == "t" ]; then
        nc=1
    fi
    if [ ${1:2:1} == "n" ]; then
        tr=0
    elif [ ${1:2:1} == "t" ]; then
        nr=1
    fi
    shift
fi
command="$1"
# Number or text value
column="$2"
row="$3"
ltrim="$4"
rtrim="$5"

columnNo=-1
rowNo=-1

exec < /dev/null

while read -r -a columns; do
    (( rowNo++ ))
    if (( columnNo == -1 )); then
        total="${#columns[@]}"
        columnNo=$(for (( i=0; i<$total; i++ ))
        {
            if [[ "${columns[$i]}" == "$column" && "$tc" == 1 ]] || [[ "$column" == "$i" && "$nc" == 1 ]]; then
                echo "$i"
                break
            elif (( i >= total - 1 )); then
                echo -1
                break
            fi
        })
    else
        if [[ "${columns[0]}" == "$row" && "$tr" == 1 ]] || [[ "$rowNo" -eq "$row" && "$nr" == 1 ]]; then
            str="${columns[columnNo]}"
            str=${str#"$ltrim"}
            str=${str%"$rtrim"}
            echo "$str"
            exit 0
        fi
    fi
done < <($command 2> /dev/null)
echo "Error! Could not be found."
exit 1

It accepts an optional flag plus 3 to 5 parameters, the command, the column (number or text value), and the row (number or text value), and optionally ltrim and rtrim values.

It works when the output contains more than one table, or the output contains extra text that isn't part of the table.

./extract-table-entry.sh "cat table.txt" "Name" 1
# Output = (John)
./extract-table-entry.sh "cat table.txt" "Name" 5
# Output = (James)

To remove the brackets, we can simply specify the ltrim parameter and rtrim parameter:

Eg:

./extract-table-entry.sh "cat table.txt" "Name" 5 "(" ")"
# Output = James

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .