-2

I have an input file as below:

1001   Ivanov I.I: chess 
2021   Petrov P.P: chess, football
3352   Sidorov S.S:  
1000   Putin V.V: judo
8773   Schwarzenegger A: judo, chess, football

I expect the output as follows:

-- chess -- 
  Ivanov I.I
  Petrov P.P
  Schwarzenegger A
-- football --
  Petrov P.P
  Schwarzenegger A
-- judo --
  Putin V.V.
  Schwarzenegger A
  • 1
    Are the <p> paragraph </p> tags in your code block meant to be part of the input data, or are they your attempt to present the input file without them? To show code, you need to precede each block of code with a blank line, and each line of code needs to be prefixed with 4 spaces... To get help for the markdown syntax, click the small (?) button at the top right of the edit box. – Peter.O Aug 21 '15 at 4:42
  • 2
    This post does not meet our quality standards. Also see How to Ask – Tejas Aug 21 '15 at 10:22
2

Here's a bit of an ugly "oneliner", that does the job exactly as specified by you in the question.

for tag in `cat input |cut -d: -f2 |sed 's/<\/p>//g' |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "<p>-- $tag --</p>"; grep $tag input | awk '{print $2, $3}' | sed 's/://g' | sed 's/^/ <p>/' | sed 's/$/<\/p>/'; done;

However, I'm not writing this post solely to help you solve this precise problem: I deliberately wrote the solution in parts that do very specific things and below is an explanation of what those parts do. So if you want to learn how to use these tools in addition to just solving this specific problem, do read ahead!

Let's go through how it works, bit by bit:

for tag in - defines us a new variable called tag. This is used for the tags you need.

cat input - reads the file called input, change this name to your file name.

| is a pipe; a fun way to get data flown through a series of commands.

cut -d: -f2 - using a colon : as a delimiter character, take the second field. This nets us the text after a colon on each line.

sed 's/<\/p>//g' - removes the end paragraph tag on each line of the input.

At this point, the data would look something like this:

 chess 
 chess, football

 judo
 judo, chess, football

Next, let's get rid of the empty lines consisting of only whitespace, as some people don't have tags associated with them.

sed '/^[[:space:]]*$/d' - removes all lines that only have whitespace in them. Great!

tr "," "\\n" - replaces all commas with newlines, so that each tag will be on a separate line.

sed 's/[[:space:]]//g' - removes any extra whitespace in the beginning of lines

sort -u - sorts the tags alphabetically, and removes any repetitions. Now we have a perfect list of all tags, in order, and without repetitions:

chess
football
judo

Now, for each of those tags, one after another, we do the following:

echo "<p>-- $tag --</p>" - print out the paragraph html tags, two dashes, tag name, two dashes, and an end paragraph tag, as specified.

grep $tag input - find lines that have the specific tag

awk '{print $2, $3}' - print the name fields (Last name + initials)

sed 's/://g' - remove the colon that was considered a part of the initials by awk

sed 's/^/ <p>/' - add a paragraph tag to beginning of each line

sed 's/$/<\/p>/' - add a close paragraph tag to end of each line

done; - and we got done with it, yay!

Here's the results:

$ for tag in `cat input |cut -d: -f2 |sed 's/<\/p>//g' |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "<p>-- $tag --</p>"; grep $tag input | awk '{print $2, $3}' | sed 's/://g' | sed 's/^/  <p>/' | sed 's/$/<\/p>/'; done;
<p>-- chess --</p>
  <p>Ivanov I.I</p>
  <p>Petrov P.P</p>
  <p>Schwarzenegger A</p>
<p>-- football --</p>
  <p>Petrov P.P</p>
  <p>Schwarzenegger A</p>
<p>-- judo --</p>
  <p>Putin V.V</p>
  <p>Schwarzenegger A</p>

EDIT: It was mentioned that the tags are not a part of the input. This simplifies things a bit:

$ for tag in `cat input |cut -d: -f2 |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "--$tag --"; grep $tag input | awk '{print $2, $3}' | sed 's/://g'; done; 
--chess --                                                        
Ivanov I.I
Petrov P.P
Schwarzenegger A
--football --
Petrov P.P
Schwarzenegger A
--judo --
Putin V.V
Schwarzenegger A
  • Oh Sorry .. Tags are not part of input. – sharanaprasad mailar Aug 21 '15 at 9:56
  • Thanks So much Walther ... I removed those tags from your command .. It works perfectly.. Thanks a lot – sharanaprasad mailar Aug 21 '15 at 10:07
  • No problem! If you think this was useful, please mark the solution as accepted. – Walther Aug 21 '15 at 10:47
0
awk -F: '{
    sub( "[ 0-9]+", "", $1 )
    gsub( " +", "", $2 )
    cz=split( $2,comp,"," )
    for( c=1; c<=cz; c++ ) {
        if( comp[c] ) {
            if( ! allcomp[comp[c]] ) 
                fifocomp[++fifoc] = comp[c]
            allcomp[comp[c]] = allcomp[comp[c]] "  " $1 "\n" 
        }
    }
} END {
    for( c=1; c<=fifoc; c++ ) {
        print "-- " fifocomp[c] " --"
        printf "%s", allcomp[fifocomp[c]]
    }
}' file

output:

-- chess --
  Ivanov I.I
  Petrov P.P
  Schwarzenegger A
-- football --
  Petrov P.P
  Schwarzenegger A
-- judo --
  Putin V.V
  Schwarzenegger A

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.