How to print the initials with awk

Viewed 138

I have this input text file:

Pedro Paulo da Silva
22 years old
Brazil

Bruce Mackenzie
30 years old
United States of America

Lee Dong In
26 years old
South Korea

The name of the person is always the first line of the file (and the first line after the empty line /n).

I have to do this output (ignoring everything except the names in the first lines):

PedroPdS
BruceM
LeeDI

Don't know how to do that with awk. I just know that awk 'print {$number}' will grab the column $number and that's how I'm supposed to grab their names.

I've searched here and found this: sed -e 's/$/ /' -e 's/\([^ ]\)[^ ]* /\1/g' -e 's/^ *//' But I have to use awk.

9 Answers

Would you please try the following:

awk -v RS="" -F '\n' '                  # records are separated on blank lines by setting RS to null
{
    n = split($1, b, " ")               # split the name on spaces
    init = b[1]                         # the first name
    for (i = 2; i <= n; i++)            # loop over the remaining
        init = init substr(b[i], 1, 1)  # append the initial
    print init
}' input.txt

Output:

PedroPdS
BruceM
LeeDI
$ cat input
Pedro Paulo da Silva
22 years old
Brazil

Bruce Mackenzie
30 years old
United States of America

Lee Dong In
26 years old
South Korea
$ awk '!a{ printf "%s", $1; 
            for( i = 2; i <= NF; i++ ) printf("%c", $i); 
            printf "\n"; a=1}
        /^$/{a=0}' input
PedroPdS
BruceM
LeeDI

With your shown samples, please try following once.

awk '
!NF{
  count=0
  next
}
++count==1{
  printf("%s%s",$1,NF==1?ORS:"")
  for(i=2;i<=NF;i++){
    printf("%s%s",substr($i,1,1),i==NF?ORS:"")
  }
}' Input_file

Explanation: Adding detailed explanation for above.

awk '                               ##Starting awk program from here.
!NF{                                ##Checking if line is empty then do following.
  count=0                           ##Setting count to 0 here.
  next                              ##next will skip all further statements from here.
}
++count==1{                         ##Checking condition if count is 1 then do following.
  printf("%s%s",$1,NF==1?ORS:"")    ##Using printf to print $1 followed by new line OR nothing.
  for(i=2;i<=NF;i++){               ##Starting a for loop here.
    printf("%s%s",substr($i,1,1),i==NF?ORS:"") ##Using printf to print sub string of current line from field 2 to last field of line and printing only 1st character of line.
  }
}' Input_file                       ##Mentioning Input_file name here.

I would use GNU AWK for this task following way, let file.txt content be

Pedro Paulo da Silva
22 years old
Brazil

Bruce Mackenzie
30 years old
United States of America

Lee Dong In
26 years old
South Korea

then

awk '{if(prevline==""){print gensub(/ ([[:alpha:]])[[:alpha:]]+/, "\\1", "g")};prevline=$0}' file.txt

output

PedroPdS
BruceM
LeeDI

Explanation: there are two things to do, first select which lines to print, then change their content into initials. For first I check if previous line (prevline) is empty string, GNU AWK if variable was not set earlier treat it as empty string for comparison with another string, so condition is meet for first line, then after processing each line I set prevline to line content ($0) so in next turn it does hold previous line. For conversion into initials I harness gensub function - I instruct AWK to replace space-letter-letters using letter and print such changed line.

(tested in gawk 4.2.1)

You can try this:

awk -F ' ' 'BEGIN {X = 1} NR == X{print $1 substr($2, 1, 1) substr($3, 1, 1) substr($4, 1, 1); X += 4}'

Another potential option is:

awk '/[0-9]/{print p} {p=$1 substr($2, 1, 1) substr($3, 1, 1) substr($4, 1, 1) substr($5, 1, 1)}' file

Another variation with a mix from the existing answers.

awk '{
  if (!x) {                      # Variable x is empty at the start or set to empty line
    res=$1                       # Set res to field 1
    for(i=2; i<=NF;i++) {        # Loop the rest of the fields starting at field 2
      res = res substr($i, 1, 1) # Concat the first char from each field with res
    }
    print res
  }
  x=$0                           # Set x variable to the value of the current line
}
' file

Output

PedroPdS
BruceM
LeeDI

With GNU awk in paragraph mode and using gensub() function you can get it:

awk 'BEGIN {RS = ""; FS = "\n"} {print gensub(/([[:space:]])([[:alpha:]]{1})([^[:space:]+])+/,"\\2","g",$1)}' file
PedroPdS
BruceM
LeeDI

Yet another. It turned out a bit like @WilliamPursell's, though (++):

$ awk '!p{for(i=1;i<=NF;i++)printf (i==1?"%s%s":"%c%s"),$i,(i==NF?ORS:"")}{p=NF}' file

Output:

PedroPdS
BruceM
LeeDI

"Explained":

$ awk '
!p {                                                   # if previous record empty
    for(i=1;i<=NF;i++)                                 # process record for ...
        printf (i==1?"%s%s":"%c%s"),$i,(i==NF?ORS:"")  # ... output
}
{ p=NF }' file                                         # store field count 
Related