在 BASH 中将电子邮件 ID 中的所有第一个字符转换为大写

在 BASH 中将电子邮件 ID 中的所有第一个字符转换为大写

我需要在脚本中接受电子邮件 ID 和全名,如果未提供全名,我需要从电子邮件 ID 生成名称。像这样的东西:

Case 1:
EmailID: [email protected]
Full Name: User Name
Case 2:
EmailID: [email protected]
Full Name: User Name2
Case 3:
EmailID: [email protected]
Full Name: This Is A Very Long Email Id

我已经能够通过以下步骤实现这一点:

EMAIL_ADDRESS="$1"
ID=(`echo $EMAIL_ADDRESS | cut -d'@' -f1| tr '.' ' '`)
NEW_ID=()
NUM=0
for IN_VAL in ${ID[@]}
do
    NEW_ID[$NUM]="`echo ${IN_VAL^}`"
    NUM=$((++NUM))
done
echo "${NEW_ID[@]}"

我使用的是 BASH 版本 4.1.2

我认为必须有更好的方法来实现这一目标。另外,我已经看到了一个问题,因为我假设字段分隔符将是点 (.) 字符,而不是下划线 (_) 或连字符 (-) 或其他任何字符。如果有更好的方法来做到这一点,请告诉我。谢谢。

答案1

实际上,您可以完全在 Bash 中执行此操作,无需任何外部命令,使用分词参数扩展。它甚至相当短:

[email protected]
USER=${EMAIL_ADDRESS%@*}
WORDS=( $(IFS=._- ; printf '%s ' $USER) )
echo "${WORDS[@]^}"

我将逐行进行:

USER=${EMAIL_ADDRESS%@*}

这会将变量设置为末尾不匹配的USER部分- 即删除域名并仅保留地址的用户部分。EMAIL_ADDRESS@*

WORDS=( $(IFS=._- ; printf '%s ' $USER) )

这会创建一个初始化大批 WORDS。初始值由以下结果给出命令替换$(...)

命令替换运行在子外壳,因此我们可以安全地更改变量的值,而不会影响它们在主 shell 中的值。其中包括IFS, 在期间使用分词作为导致新单词开始的一组字符。._、 和中的每一个-都会形成一个单词边界,如果您愿意,您可以在其中添加新字符。

改变后IFS我们使用printf打印出$USER已被拆分成的单词,这比更安全一些echo

echo "${WORDS[@]^}"

最后,我们打印出结果。如您所知,是[@]数组扩展,然后^ 执行大写单词中第一个字符的值(严格来说,默认模式的第一个匹配项?)。

运行该脚本的最终结果是输出:

This Is A Very Long Email Id

正如预期的那样。


如果任何电子邮件地址包含 shell 元字符*?等,它们将被扩展为通配符。您可以将该WORDS=行换行到set -f/set +f以避免这种情况,但还有另一种选择(由评论中的 Glenn Jackman 提供)。

IFS=._- read -r -a WORDS <<<"${EMAIL_ADDRESS%@*}"
echo "${WORDS[@]^}"

这使用read -a用分词的结果填充一个数组,其余的(压缩的)和以前一样。我发现这比显式数组初始化读起来不太清晰,但它是一个选项。

还值得注意的是,电子邮件地址可以严格来说有多种多样的形式,包括其中包含空格、引号和括号字符的地址,这根本不处理这些地址(考虑到您的问题规范,也不可能真正这样做)。

答案2

使用 sed:

sed 's/@.*//; s/[-_.]/ /g; s/\<./\U&/g' <<END
[email protected]
[email protected]
[email protected]
END
User Name
User Name2
This Is A Very Long Email Id

大写指令需要 GNU sed \U

https://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-命令

扩展:

sed '
    s/@.*//        # remove @domain.name
    s/[-_.]/ /g    # translate dot,dash,underscore to spaces
    s/\<./\U&/g    # uppercase the first character of a word
                   # \< is a beginning-of-word marker
'

一段难以理解的 Perl 一行行:

perl -nE's/@.*//;say"@{[map{ucfirst}/(\w+)/g]}"' 

由于 Perl 的\w字符类快捷方式包含下划线,
[email protected]因此变为
This Is A Very Long_email Id

相关内容