user1754493
user1754493

Reputation: 215

Perl regex replace first name last name with first name last initial

I want to have the output of $var below to be John D

my $var = "John Doe";

I have tried $var =~ s/(.+\b.).+\z],'\1.'//g;

Upvotes: 1

Views: 1398

Answers (6)

amon
amon

Reputation: 57640

A simple regex that solves this problem is the substitution

s/^\w+\s+\K(\w).*/\U$1/s

What does this do?

  • ^ \w+ \s+ matches a word at the beginning of the string, plus whitespace towards the next word
  • \K is the keep escape. It keeps the currently matched part outside of that substring that is considered “matched” by the regex engine. This avoids an extra capture group, and is practically a look-behind.
  • (\w) matches and captures one “word” character. This is the leading character of the second word in the string.
  • .* matches the rest of the string. I do this to overwrite any other names that may come: you stated that Lester del Ray should be transformed to Lester D, not Lester D Ray as a solution with \w* instead of the .* part would have done. The /s modifier is relevant for this, as it enables . to match every character including newlines (who knows what's inside the string?).
  • The substitution uses the \U modifier to uppercase the rest of the string, which consists of the value of the capture.

Test:

$ perl -E'$_ = shift; s/^\w+\s+\K(\w).*/\U$1/s; say' "Lester del Ray"
Lester D
$ perl -E'$_ = shift; s/^\w+\s+\K(\w).*/\U$1/s; say' "John Doe"
John D

Upvotes: 0

K Tatyana
K Tatyana

Reputation: 1

$var = "John Doe";
s/^(\w+)\s+(\w)/$1 \u$2/ for $var;

Upvotes: 0

Matt Ritter
Matt Ritter

Reputation: 31

Here's a general solution (feel free to swap in '\w' where I used '.', and add a \s where I used \s+)

my $var = "John Doe";
(my $fname, my $linitial) = $var =~ /(.*)\s+(.).*/

Then you have the values

$fname = 'John';
$linitial = 'D';

and you can do:

print "$fname $linitial";

to get

"John D"

EDIT Until you do your next match, each of the capture parentheses creates a variable ($1 and $2, respectively), so the whole thing can be shortened a bit as follows:

my $var = "John Doe";
$var =~ /(.*)\s+(.).*/
print "$1 $2";

Upvotes: 3

Kalyan02
Kalyan02

Reputation: 1434

Assuming your string has ascii names this will work

$var =~ s/([a-zA-Z]+)\s([a-zA-Z]+)/$1." ".substr($2,0,1)/ge;

Upvotes: 0

Borodin
Borodin

Reputation: 126722

To replace the last sequence of non-whitespace characters with just the initial character, you could write this

use strict;
use warnings;

my $var = "John Doe";

$var =~ s/(\S)\S*\s*$/$1/;

print $var;

output

John D

Upvotes: 1

Zach Leighton
Zach Leighton

Reputation: 1941

Something like this might be a little more usable/reusable in the long run.

$initial = sub { return substr shift, 0, 1 ; };

make a get initial function

$var =~ s/(\w)\s+(\w)/&$initial($1) &$initial($2)/sge;

Then replace the first and second results using execute in the regex;

Upvotes: -1

Related Questions