【问题标题】:Regex to grab full firstname and first letter of last name正则表达式获取完整的名字和姓氏的第一个字母
【发布时间】:2016-05-10 02:52:49
【问题描述】:

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

Thomas_J_Perkins

Jennifer_Scanner

Amanda_K_Loso

亚伦科尔

Mark_L_Lamb

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

托马斯·P

詹妮弗·S

阿曼达·L

亚伦C

马克L

我不知道该怎么做,我试过抓取所有字符:/\w+/,但这会抓取所有内容。

【问题讨论】:

  • 定义“名字”和“姓氏”。在什么文化中?不要假设名字首先出现;您可能会因未正确处理客户姓名而无意中侮辱客户。阅读“How to Ask”(包括链接)和“minimal reproducible example”。我们希望看到您的努力的证据。看起来您似乎没有尝试过并希望我们为您编写代码,这是题外话,或者为您编写教程,这又是题外话。

标签: ruby regex


【解决方案1】:

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

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

你可以用一些简单的 Ruby 代码来做到这一点

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

【讨论】:

  • 只是输入相同的内容。
  • 很好的答案,但两次调用string.split("_") 是不必要的。
  • @amdouglas 即使没有中间名首字母,这仍然有效吗?
  • @JasonBorne 是的,它需要完整的第一个单词和最后一个单词的第一个字母。不管你有两三个字。
【解决方案2】:

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

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"

【讨论】:

    【解决方案3】:

    你可以使用

    ^([^\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+个_序列+里面的字母(带有(?:_\p{L}+)*_),然后匹配并捕获最后一个单词的第一个字母(使用(\p{L})),然后匹配字符串的其余部分(使用\p{L}*)。

    注意:如果您有独立的字符串,请将@​​987654337@ 替换为\A,将$ 替换为\z(如在Ruby 中,^ 匹配行首,$ 匹配行尾) .

    Ruby code:

    s.sub(/^(\p{L}+)(?:_\p{L}+)*_(\p{L})\p{L}*$/, "\\1_\\2")
    

    【讨论】:

    【解决方案4】:

    我在这个阵营中不要使用正则表达式。

    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 = /(.+?)(?=_)(?:.*)(?:_)(.)/
    

    【讨论】:

      【解决方案5】:

      这是我的尝试:

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

      demo

      【讨论】:

        【解决方案6】:

        让我们看看这是否有效:

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

        然后您必须将第一个和第二个匹配项组合成您想要的格式。我不了解 Ruby,所以我无法帮助您。

        【讨论】:

          【解决方案7】:

          又一次尝试使用替换方法:

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

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

          【讨论】:

            【解决方案8】:

            使用拆分方法会好很多

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

            【讨论】:

            • 我建议first, last = full_name.split('_').values_at(0,-1); first+last[0]
            【解决方案9】:

            /^[A-Za-z]{5,15}\s[A-Za-z]{1}]$/i 这将具有以下标准: 名字 5-15 个字符,然后是空格,最后是姓氏一个字符。

            【讨论】:

            • Never, ever restrict names to word characters. 此外,名为“Bill”、“Paul”或“Anne”的人可能对 5-15 个字符的标准有疑问。 \s 在你的模式中做了什么?
            • \s 表示一个空格,因此名字和姓氏之间有一个空格。如果长度是一个问题,那么您可以随时使用 {,upperLimit}。
            • 重点是,由于\s,您的模式不起作用。您想匹配下划线,而不是空格。
            • 在这种情况下:/^[A-Za-z]{2,15}[_]{1}[A-Za-z]{1}]$/i
            • 我开始认为您误解了 OP 的问题。你的模式不应该匹配像“Mark L”这样的名字,它应该把“Mark_L_Lamb”变成“Mark L”。
            猜你喜欢
            • 2020-09-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-31
            相关资源
            最近更新 更多