首页 > 解决方案 > 如何让 sed 记忆模式产生预期的输出?

问题描述

我试图让替换模式提取名字的第一个字母(假定为大写)和整个姓氏,但忽略任何中间名'

例如:
John Doe应该产生JDoe
John Andrew DoeJDoe也应该产生

我已经尝试了以下方法,我得到的只是我输入的内容,John Doe

echo 'John Doe ' | sed -E 's/\([A-Z]\){1}((a-z)+) ([A-Z][a-z]+)* \([A-Z]{1}[a-z]+\)/\1/g'

标签: regexbashsed

解决方案


使用sed和扩展正则表达式,您可以执行以下操作:

$ echo "John Doe" | sed -r 's/^(\w).*\s(\w+)$/\u\1\u\2/'
JDoe

或在中间放置任意数量的字符,然后在其后加一个空格,"John"结果"Doe"是相同的:

$ echo "John Andres Doe" | sed -r 's/^(\w).*\s(\w+)$/\u\1\u\2/'
JDoe

基本上:

  • 定位\w锚定在开头的第一个(单词字符)并将字符收集到(...)捕获组中;
  • .*\s跳过后跟空格字符的任意数量的字符;
  • \w+$收集输入中的最终单词;
  • 没有人对第一个字符的情况做出任何假设
  • 替换是\u\1\u\2\u第一个字符转换为大写的地方,\1并且\2是反向引用重新插入捕获组中捕获的内容。

例如:

$ echo "john james dan doe" | sed -r 's/^(\w).*\s(\w+)$/\u\1\u\2/'
JDoe

看看事情,如果你有问题,请告诉我。


推荐阅读