我正在寻找一些提示,如何才能找到更好、更优雅、更高效的解决方案。所以我有一个包含姓名列表的文件。
名称.txt:
Doe John
del Super Mario
van Hoppity Jenny
van der Hupfburg Susi
Smith-Osborne John Marc
期望输出:
John Doe
Mario del Super
Jenny van Happity
Susi van der Hupfburg
John Marc Smith-Osborne
如您所见,排序顺序为“姓氏”后跟“姓名”,没有特定的分隔符(只有空格)将姓氏与姓名分开。我想要的是名字而不是姓氏。在大多数情况下,第一个单词是姓氏。在某些情况下,有一个前缀,如“van”或意大利语“del”。为了将这些前缀附加到姓氏,我想用破折号替换空格 - 这样它们就变成了一个单词(van-Hoppity、van-der-Hupfburg 等),我可以将第一个单词移动到行尾,
我当前的 sed 解决方案正在运行,但是随着每个新前缀的发现,行变得越来越长。
所以我想使用 awk,使用包含搜索模式(前缀列表)的文件,该文件应该在名称文件中找到该模式并替换它。
所以2个文件
- 姓名.txt
- 模式.txt
pattern.txt 包含第二个字段中的前缀和替代替换。字段分隔符为“;”
模式.txt:
del ;del-
van der ;van-der-
van ;van-
awk 应该使用 pattern.txt 在 names.txt 中搜索,并将找到的匹配项替换为 pattern.txt 中字段 2 的值
有什么想法、提示或建议吗?
答案1
据我所知,您的文本文件(这是一种存储此类数据的糟糕方式)可以解释为:
- 每行包含一个名称
- 姓氏可以以零个或多个单词的全小写前缀开头(例如“van”,“del”,“van der”),后跟一个大写单词
暗示:列表不包含类似“杜姆·维克托“ - 用空格隔开:
- 一个或多个名字
在可能的正则表达式上制作捕获组(family Name) <space> (First Name(s))
是(^[^A-Z]*[A-Z][^ ]*) (.*$)
。
我使用的正则表达式解释如下:https://regex101.com/r/kOjwiS/1
并将其倒入 bash 代码片段中:
#!/bin/bash
regex="(^[^A-Z]*[A-Z][^ ]*) (.*$)"
while read line ; do
[[ "$line" =~ $regex ]]
echo "Firstname(s): ${BASH_REMATCH[2]}"
echo "Family Name: ${BASH_REMATCH[1]}"
done < names.txt
Firstname(s): John
Family Name: Doe
Firstname(s): Mario
Family Name: del Super
Firstname(s): Jenny
Family Name: van Hoppity
Firstname(s): Susi
Family Name: van der Hupfburg
Firstname(s): John Marc
Family Name: Smith-Osborne