使用sed替换制表符时,输入无制表符导致无输出如何解决?
sed制表符替换导致单姓名行无输出的问题排查与解决
问题描述
尝试从网站提取姓名列表时遇到sed处理异常:
- 执行以下命令可获取9月12日的姓名(姓名间以制表符分隔):
curl -s "https://namnidag.se/?year=2022&month=9&day=12" | sed -nE -e "s#<div class='names'>([^<]*)</div>#\1#p" | html2text
输出:
Åsa Åslög
- 修改脚本替换制表符为逗号加空格后,9月12日可正常输出:
curl -s "https://namnidag.se/?year=2022&month=9&day=12" | sed -nE -e "s#<div class='names'>([^<]*)</div>#\1#" -e 's/\t/, /p' | html2text
输出:
Åsa, Åslög
- 但处理只有单个姓名的9月13日时,该脚本无输出,而未添加制表符替换的脚本可正常运行:
curl -s "https://namnidag.se/?year=2022&month=9&day=13" | sed -nE -e "s#<div class='names'>([^<]*)</div>#\1#" -e 's/\t/, /p' | html2text
问题原因
你启用了sed -n静默模式,这个模式下sed不会自动输出任何行,只有执行带p标记的命令时才会输出内容:
- 第一个sed命令仅完成姓名提取的替换,但没有加
p,因此不会输出; - 第二个命令
s/\t/, /p只有在找到制表符并替换成功时,才会触发p输出; - 单姓名的行里没有制表符,第二个命令执行失败,不会输出内容,最终无任何结果。
而最初的脚本里第一个提取命令带了p,不管有没有制表符都会输出处理后的行,所以单姓名场景正常。
解决方案
有两种简单的修复方式:
方式1:确保所有处理后的行都输出
在sed命令末尾添加单独的p命令,不管制表符替换是否成功,都会输出提取后的姓名行:
curl -s "https://namnidag.se/?year=2022&month=9&day=13" | sed -nE -e "s#<div class='names'>([^<]*)</div>#\1#" -e 's/\t/, /g' -e p | html2text
(这里把s/\t/, /p改成s/\t/, /g去掉p,最后单独加p,g确保一行多个制表符都被替换)
方式2:合并命令并统一输出
把提取和替换合并到一个逻辑里,最后用p输出:
curl -s "https://namnidag.se/?year=2022&month=9&day=13" | sed -nE -e "s#<div class='names'>([^<]*)</div>#\1#; s/\t/, /g; p" | html2text
这两种方式都能保证不管是单姓名还是多姓名的行,都会被正确提取、替换(如果有制表符)并输出。
内容的提问来源于stack exchange,提问作者Chipskate
相关产品推荐
相关产品推荐

