正则表达式获取完整的名字和姓氏的第一个字母

时间:2016-05-09 15:46:18

标签: ruby regex

我有一个由Etc Ruby库抓取的用户列表:

  

Thomas_J_Perkins

     

Jennifer_Scanner

     

Amanda_K_Loso

     

Aaron_Cole

     

Mark_L_Lamb

我需要做的是获取完整的名字,跳过中间名(如果给出),并抓住姓氏的第一个字符。输出应如下所示:

  

Thomas P

     

Jennifer S

     

Amanda L

     

Aaron C

     

Mark L

我不确定如何做到这一点,我已经尝试抓住所有角色:/\w+/但是这样可以抓住所有角色。

9 个答案:

答案 0 :(得分:6)

我认为没有正则表达式会更简单:

array = "Thomas_J_Perkins".split("_") # split at _
array.first + " " + array.last[0] # .first prints first name .last[0] prints first char of last name
#=> "Thomas P"

答案 1 :(得分:5)

你并不总是需要正则表达式。

  

有些人在面对问题时会想到,我知道,我会使用   正则表达式。"现在他们有两个问题。 Jamie Zawinski

您可以使用一些简单的Ruby代码

来完成
string = "Mark_L_Lamb"
string.split('_').first + ' ' + string.split('_').last[0]
=> "Mark L"

答案 2 :(得分:1)

您可以使用

^([^\W_]+)(?:_[^\W_]+)*_([^\W_])[^\W_]*$

并替换为\1_\2。请参阅regex demo

[^\W_]匹配字母或数字。如果您只想匹配字母,请将[^\W_]替换为\p{L}

^(\p{L}+)(?:_\p{L}+)*_(\p{L})\p{L}*$

请参阅updated demo

重点是匹配并捕获第一个字母到第一个_(带(\p{L}+)),然后匹配_ +个字母的0 +序列(带{ {1}})然后匹配并捕获最后一个单词的第一个字母(带(?:_\p{L}+)*_),然后匹配字符串的其余部分((\p{L}))。

注意:如果您有独立字符串,则将\p{L}*替换为^,将\A替换为$(如在Ruby \z中匹配行的开头, ^匹配行尾。)

Ruby code

$

答案 3 :(得分:1)

我正处于这个阵营中不使用的正则表达式。

str1 = "Alexander_Graham_Bell"
str2 = "Sylvester_Grisby"

"#{str1[0...str1.index('_')]} #{str1[str1.rindex('_')+1]}"
  #=> "Alexander B"
"#{str2[0...str2.index('_')]} #{str2[str2.rindex('_')+1]}"
  #=> "Sylvester G"

first, last = str1.split(/_.+_|_/)
  #=> ["Alexander", "Bell"] 
first+' '+last[0]
  #=> "Alexander B" 

first, last = str2.split(/_.+_|_/)
  #=> ["Sylvester", "Grisby"] 
first+' '+last[0]
  #=> "Sylvester G" 

但如果你坚持......

r = /
    (.+?)     # match any characters non-greedily in capture group 1
    (?=_)     # match an underscore in a positive lookahead 
    (?:.*)    # match any characters greedily in a non-capture group 
    (?:_)     # match an underscore in a non-capture group
    (.)       # match any character in capture group 2
    /x        # free-spacing regex definition mode

str1 =~ r
$1+' '+$2
  #=> "Alexander B"

str2 =~ r
$1+' '+$2
  #=> "Sylvester G"

你当然可以写

r = /(.+?)(?=_)(?:.*)(?:_)(.)/

答案 4 :(得分:0)

这是我的尝试:

/([a-zA-Z]+)_([a-zA-Z]+_)?([a-zA-Z])/

请参阅demo

答案 5 :(得分:0)

让我们看看这是否有效:

/^([^_]+)(?:_\w)?_(\w)/

然后你必须将第一和第二场比赛组合成你想要的格式。我不认识Ruby,所以我无法帮助你。

答案 6 :(得分:0)

使用替换方法的另一种尝试:

result = subject.gsub(/^([^_]+)(?:_[^_])?_([^_])[^_]+$/, '\1 \2')

我们捕获整个字符串,捕获组中的相关部分。然后只返回两个捕获的组

答案 7 :(得分:0)

使用split方法要好得多

full_names.map do |full_name|
   parts = full_name.split('_').values_at(0,-1)
   parts.last.slice!(1..-1)
   parts.join(' ')
end

答案 8 :(得分:-1)

/ ^ [A-ZA-Z] {5,15} \ S [A-ZA-Z] {1}] $ / I 这将具有以下标准: 首字母为5-15个字符,然后是空格,最后是姓氏的单个字符。