# Get username from full name - PowerShell function

I would like your opinion of my PowerShell function. Does it follow conventions, and what could can I do to improve it. It is made to create LDAP friendly username from a full name in Serbian language.

function Get-UsernameFromFullName
{
[CmdletBinding()]
param
(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName =$true)]
[string]
$FullName, [Parameter(Position = 1, Mandatory =$false, ValueFromPipelineByPropertyName = $true)] [ValidateSet('First', 'Last')] [string]$LastNamePosition = 'First'
)

$usernameComponents =$FullName.ToLower().Split(" ")

switch ($LastNamePosition) { 'First' {$firstName = $usernameComponents.Length -1;$lastName = 0 }
'Last'  { $firstName = 0;$lastName = $usernameComponents.Length -1 } Default {$firstName = $usernameComponents.Length -1;$lastName = 0 }
}

$chars = ($usernameComponents.Get($firstName) + "." +$usernameComponents.Get($lastName)).ToCharArray() foreach($char in $chars) { switch($char)
{
'ć' { $segment = "c" } 'č' {$segment = "c" }
'đ' { $segment = "dj" } 'š' {$segment = "s" }
'ž' { $segment = "z" } default {$segment = $char } }$Username += $segment } return$Username
}


Here is a link to GitHub page of the actual .psm1 file.

This is an example of the function usage:

Get-UsernameFromFullName -FullName "Čedomir Đorđević"


cedomir.djordjevic

Get-UsernameFromFullName -FullName "JANKOV ZORAN"


zoran.jankov

Get-UsernameFromFullName -FullName "Stojić Gradimir"


Get-UsernameFromFullName -FullName "Vučićević R Željko"


zeljko.vucicevic

Get-UsernameFromFullName -FullName "Magda Boškić" -LastNamePosition Last


magda.boskic

• could you add some sample names & the result from processing them? i have a hard time thinking about things without something solid to work with ... [blush] Aug 4, 2020 at 2:04
• PLEASE, do not post images of text/code/sample-data/errors. why force others to squint to read it ... or to type it in to test it? for example, the reason to ask for samples is to see how the code runs when given sample data to work with. i am not willing to type up 4-5 sample names just to help test your code. so please post the requested sample data in a usable format - text. [grin] Aug 4, 2020 at 7:40
• yep! [grin] all i needed was the names, not the command line ... but that gives me some sample data to work with after i strip out the commands. i have a few ideas, so i otta have a bit of commentary sometime in the next 18 hours or so. gotta take care of "real life" 1st ... [grin] Aug 5, 2020 at 4:05
• Please do not edit the code after you have an answer! See our help center Aug 5, 2020 at 12:52
• @ZoranJankov - thank you for the info ...i was wondering why ... [grin] Aug 5, 2020 at 13:28

i think the comments cover the why of things, but please feel free to ask if you have any questions. [grin]

#region >>> fake reading in a list of names
#    in real life, use Get-Content
$InStuff = @' Čedomir Đorđević JANKOV ZORAN Stojić Gradimir Vučićević R Željko Magda Boškić '@ -split [System.Environment]::NewLine <# intended output cedomir.djordjevic zoran.jankov gradimir.stojic zeljko.vucicevic magda.boskic [lastname @ end] #> #endregion >>> fake reading in a list of names function Get-UserNameFromFullName # your "Get-UsernameFromFullName" name leaves the "N" in "Username" in lowercase # that is not consistent with your use of that in other names of items { <# where is the Comment Based Help? #> [CmdletBinding ()] Param ( [Parameter ( Position = 0, # the following are switches that default to "$False"
#    that means there is no need to add "= $True" # the simple presense of the attribute flips it to "$True"
Mandatory,
ValueFromPipeline,
# the following requres the pipeline object contain a property named ".FullName"
#    is that always going to be the case?
#    if not, then the "ValueFromPipeline" above will handle bare values
ValueFromPipelineByPropertyName
)]
[string]
$FullName, [Parameter ( Position = 1, # making this mandatory makes little sense when a default is supplied #Mandatory, # does it make any sense to use the following attribute? ValueFromPipelineByPropertyName )] # don't use "First" and "Last" for _position_ info when the same words are used for the name parts # it's needlessly confusing #[ValidateSet ('First', 'Last')] [ValidateSet ('Start', 'End')] [string]$LastNamePosition = 'Start'
)

begin {}

process
{
# properly supporting the pipeline requires one to have a "process" block.
#    otherwise all code is run in a virtual "end" block ... and that does not correctly support pipeline input

# mixing camelCase and PascalCase for variable names is confusing [*grin*]
#    the recommended style for PoSh is PascalCase
#$usernameComponents =$FullName.ToLower().Split(" ")
# the 2nd sample name has a trailing space
#    the ".Trim()" removes that
# good practice in PoSh is to avoid using double quotes since that can trigger unwanted expansion of $Vars$UserNameComponents = $FullName.Trim().ToLower().Split(' ') switch ($LastNamePosition)
{
'Start' {
# "index -1, index 0" for the $UserNameComponents skips any middle name or initial$UserName = '{0}.{1}' -f $UserNameComponents[-1],$UserNameComponents[0]
}
'End' {
$UserName = '{0}.{1}' -f$UserNameComponents[0], $UserNameComponents[-1] } # this is a binary choice, so the "default" is not needed #Default {$firstName = $UserNameComponents.Length -1;$lastName = 0 }
}

# there is no need to assign the output to anything
#    whatever is left unassigned will be sent out
# there is also no need for "return"
#    that is disrecommeded since it gives the false impression that ONLY the item to its right will be returned
# the "-replace" operator can be chained. so can the ".Replace()" method
#    that allows us to skip breaking things into an array of chars
$UserName -replace 'č', 'c' -replace 'ć', 'c' -replace 'đ', 'dj' -replace 'š', 's' -replace 'ž', 'z' } # end >>> process end {} } # end >>> function Get-UserNameFromFullName  run with all names, no parameters, and using the pipeline ... $InStuff |


output ...

djordjevic.cedomir
zoran.jankov
zeljko.vucicevic
boskic.magda


run with all parameters listed and only one input value ...

Get-UserNameFromFullName -FullName $InStuff[-1] -LastNamePosition End  output = magda.boskic • Thank you for your great advice! I have created a new version of my function based on your suggestions. Aug 8, 2020 at 15:15 • @ZoranJankov - you are most welcome! glad to have helped somewhat ... [grin] Aug 9, 2020 at 5:27 I have created a new version of my function based on Lee_Dailey suggestions. function Get-UserNameFromFullName { [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [string]$FullName,

[Parameter(Position = 1, ValueFromPipelineByPropertyName)]
[switch]
$ReverseNamePositions =$false
)

process
{
if ($ReverseNamePositions) {$Front = -1
$End = 0 } else {$Front = 0
$End = -1 }$UserNameComponents = $FullName.Trim().ToLower().Split(' ')$UserName = '{0}.{1}' -f $UserNameComponents[$Front], $UserNameComponents[$End]

\$UserName -replace 'č', 'c' 
-replace 'č', 'c'
-replace 'ć', 'c' 
-replace 'đ', 'dj'
-replace 'š', 's' 
-replace 'ž', 'z'
}
}
`

If someone thinks that the function is lacking something feel free to tell me. I would be grateful.

• backticks are ... problematic ... in that they are easy to overlook. that means you can do some editing, leave one behind, and then spend HOURS tracking down the reason for your code misbehaving. [grin] try to avoid the backtick whenever you can. that is why i used that odd-looking structure in my version. ///// otherwise, very neat code! [grin] Aug 9, 2020 at 5:30