如何在Bash中从指定格式字符串提取名称并处理空行?
问题:提取包含空格的名称(排除后续数字/数字对)
输入数据格式为 <name> <a>/<b>,同一行可能出现0次或多次,且/两侧可能存在多余空格。需要提取出的目标名称示例如下:
name1 name2 name3 last3
现有错误代码:
echo "name1 11/22 name2 33 / 44 name3 last3 55/66" \ | grep -o -E '\b[a-zA-Z][a-zA-Z0-9. ]+\b'
错误输出(错误地把数字也包含进名称):
name1 11 name2 33 name3 last3 55
要求:脚本处理空行时无输出,以下是几种可行的Bash实现方法:
方法1:使用sed(简洁高效)
echo "name1 11/22 name2 33 / 44 name3 last3 55/66" | sed -E 's/([a-zA-Z][a-zA-Z0-9. ]*)[[:space:]]+[0-9]+[[:space:]]*\/[[:space:]]*[0-9]+/\1\n/g; s/[[:space:]]*$//'
说明:
- 正则匹配完整的
<name> <a>/<b>单元,将名称部分保留,替换为名称\n - 最后一步去掉末尾多余空格,空行因无匹配项直接输出为空
方法2:使用awk(逻辑清晰,易扩展)
echo "name1 11/22 name2 33 / 44 name3 last3 55/66" | awk '{ name = "" next_is_slash = 0 for (i=1; i<=NF; i++) { if ($i ~ /^[0-9]+[[:space:]]*\/[[:space:]]*[0-9]+$/) { print name name = "" } else if ($i ~ /^[0-9]+$/) { if (next_is_slash) { next_is_slash = 0 print name name = "" } else { next_is_slash = 1 } } else if ($i == "/") { next_is_slash = 0 print name name = "" } else { name = (name ? name " " : "") $i } } }'
说明:
- 逐字段遍历输入,区分名称、数字、
/三种类型的字段 - 遇到完整的
<a>/<b>或拆分的<a> / <b>时,输出之前累加的名称并重置状态 - 空行时字段数为0,循环不执行,无输出
方法3:使用支持PCRE的grep(简洁的正则匹配)
echo "name1 11/22 name2 33 / 44 name3 last3 55/66" | grep -o -P '[a-zA-Z][a-zA-Z0-9. ]*(?=\s+(?:\d+\s*\/\s*\d+|\d+\s+\/\s+\d+))'
说明:
- 利用正向预查(
(?=...))匹配后面紧跟<a>/<b>或<a> / <b>的名称部分 - 仅提取符合条件的名称,不会包含后续数字;空行无匹配项,输出为空
内容的提问来源于stack exchange,提问作者Daniel YC Lin
相关产品推荐
相关产品推荐

