0

I need help with bash scripting. Below is my input:

Grp: MG1
user1 
user2 
user3 
Grp: MG2
user7 
user1 
user9 
user6 
user2 

The result should look like:

Reporting MG1
MG1,user1 
MG1,user2 
MG1,user3 
Reporting MG2
MG2,user7 
MG2,user1 
MG2,user9 
MG2,user6 
MG2,user2 

I tried sed -n '/cn:/,/cn:/p' file, but it didn't do what I want.

2

3 Answers 3

3

with awk which is the right tool for text-formatting:

awk '/^Grp:/ { OFS=" "; $1= "Reporting"; mg=$2; print; next} 
             { OFS=","; print mg, $0}' infile
2
  • Very nice! The OP originally had blank lines in the input; I'm not sure if that was intentional or just poor formatting. It might be worth tweaking this a little to handle blank lines in the input just in case. Commented Apr 5, 2020 at 15:53
  • I think so and that was formatting issue. if not, pre-pending NF to the second line would be enough. Commented Apr 5, 2020 at 16:01
1

Using sed:

$ cat script.sed
/^Grp: / {                              ;# A "Grp: " line
        s///                            ;# Remove "Grp: "
        h                               ;# Save in hold space
        s/^/Reporting /p                ;# Insert "Reporting " at start, print
        d                               ;# Delete, start next cycle
}

# Any other line:
G                               ;# Append the hold space
s/\(.*\)\n\(.*\)/\2,\1/         ;# Swap strings around \n, insert comma
$ sed -f script.sed file
Reporting MG1
MG1,user1
MG1,user2
MG1,user3
Reporting MG2
MG2,user7
MG2,user1
MG2,user9
MG2,user6
MG2,user2

As a "one-liner":

sed -e '/^Grp: /{s///;h;s/^/Reporting /p;d;}' \
    -e 'G;s/\(.*\)\n\(.*\)/\2,\1/' file

A similar approach to the above with awk:

awk '/^Grp: / { sub("^Grp: ", ""); group = $0; print "Reporting " $0; next }
              { print group "," $0 }' file

Both the sed and awk variations in this answer (as well as the sh variant at the end below) would cope with spaces in the data, either in the MG strings or in the user strings:

$ cat file
Grp: some group ID
line 1
the other line
$ sed -e '/^Grp: /{s///;h;s/^/Reporting /p;d;}' -e 'G;s/\(.*\)\n\(.*\)/\2,\1/' file
Reporting some group ID
some group ID,line 1
some group ID,the other line

Just as a fun exercise, using /bin/sh:

while IFS= read -r line; do
        case $line in
                'Grp: '*)
                        group=${line#Grp: }
                        printf 'Reporting %s\n' "$group"
                        ;;
                *)
                        printf '%s,%s\n' "$group" "$line"
        esac
done

Run with

sh script.sh <file
0

Given your sample input above, you can use this:

#!/bin/bash

group=""

while read line; do
    if [[ "${line}" =~ ^Grp:* ]]; then
        group="$(echo "${line}" | awk '{ print $2 }')"
        echo "Reporting ${group}"
    elif [[ "${line}" == "" ]]; then
        echo
    else
        echo "${group},${line}"
    fi
done

For example:

$ cat input
Grp: MG1
user1
user2
user3
Grp: MG2
user7
user1
user9
user6
user2
$

$ ./ex.sh < input
Reporting MG1
MG1,user1
MG1,user2
MG1,user3
Reporting MG2
MG2,user7
MG2,user1
MG2,user9
MG2,user6
MG2,user2
$

The script runs a loop that reads a line of text. If the line begins with Grp:, then it saves the second whitespace delimited token as the group. If the line is blank, then it prints a blank line. Otherwise, it prints the last-read group, followed by a comma, followed by the content of the line.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.