sed正则行首追加内容处理不同输入时结果异常的问题
问题现象
使用echo构造测试文本执行sed替换时结果符合预期:
$ echo "1.1.1.1\n2.2.2.2" | sed "s/^/allow /g; s/$/;/g" allow 1.1.1.1; allow 2.2.2.2;
但使用完全相同的sed命令处理wget拉取的IP列表时,输出出现异常,每行开头变成;llow:
$ wget -q 对应接口地址 -O - | sed "s/^/allow /g; s/$/;/g" ;llow 84.17.46.49 ;llow 185.93.1.242 ;llow 185.152.67.139 ...
故障原因
wget拉取的接口返回内容使用的是Windows风格的CRLF(\r\n)换行符,而本地echo生成的测试文本是Unix风格的LF(\n)换行符。
sed按行读取文本时,只会自动剥离行尾的\n字符,不会处理末尾残留的\r(回车符),处理流程如下:
- 读入的每行原始内容为
[IP地址]\r - 执行
s/^/allow /替换后,内容变为allow [IP地址]\r - 执行
s/$/;/替换后,内容变为allow [IP地址]\r; - 终端输出时遇到
\r会将光标移动回当前行的起始位置,后续输出的;会覆盖行首的第一个字符a,最终就显示成了;llow [IP地址]的异常效果。本质上分号是被加到了行尾,只是回车符把光标挪回行首,导致分号覆盖了行首字符,造成了“分号加在开头、allow少了首字母”的错觉。
修复方法
在sed替换逻辑前先删除每行末尾的\r字符即可,修改后的命令如下:
wget -q 对应接口地址 -O - | sed "s/\r$//; s/^/allow /g; s/$/;/g"
也可以在管道中加dos2unix做换行格式转换后再执行sed替换,效果一致。
内容的提问来源于stack exchange,提问作者Rodrigo
相关产品推荐
相关产品推荐

