Linux下watch执行带sed管道的命令报错如何解决
问题现象
- 直接执行命令
ip -s link show enp65s0f0 | sed -n '/ vf 4/,$p',可正常输出网卡enp65s0f0对应vf 4的配置及流量统计信息。 - 尝试通过watch命令周期性执行上述命令实时查看数据变化,运行
watch "ip -s link show enp65s0f0 | sed -n '/ vf 4/,$p'"时报错:sed: -e expression #1, char 16: unexpected ','。 - 后续尝试两种修复方式均失败:
- 给sed匹配规则内的空格添加转义符,执行
watch "ip -s link show enp65s0f0 | sed -n '/\ \ \ \ vf\ 4/,$p'",仍报相同错误 - 给watch后的命令整体包裹单引号,执行
watch 'ip -s link show enp65s0f0 | sed -n '/ vf 4/,$p'',出现新报错sed: -e expression #1, char 1: unterminated address regex
- 给sed匹配规则内的空格添加转义符,执行
报错根因
watch执行传入的命令串时,会先调用shell做一层语法解析,引号嵌套处理不当会导致sed收到的执行参数残缺:
- 第一次用双引号包裹全命令时,
$p中的$属于shell双引号环境下的变量标识,会被提前解析为变量展开,由于不存在名为p的变量,展开后为空值,sed实际收到的脚本为/ vf 4/,,缺少范围结束的p命令,因此触发逗号位置的语法错误。空格本身不需要转义,加转义符自然无法解决问题。 - 第二次用单引号包裹全命令时,shell单引号语法不支持直接嵌套单引号,命令串在
sed -n后的第一个单引号处就被截断,sed收到的是残缺的正则表达式,因此触发正则未终止的错误。
正确实现方案
以下两种写法均可正常实现周期性刷新查询的需求,默认2秒刷新一次,如需调整间隔可加-n <秒数>参数,例如watch -n 1即设置为1秒刷新一次。
方案1:单引号嵌套转义写法
shell单引号字符串内无法直接包含单引号,可通过'\''的格式插入转义后的单引号,完整命令:
watch 'ip -s link show enp65s0f0 | sed -n '\''/ vf 4/,$p'\'''
方案2:双引号转义写法
将sed的脚本部分改用双引号包裹,外层全命令用双引号时,对内部双引号和$符号做转义即可,完整命令:
watch "ip -s link show enp65s0f0 | sed -n \"/ vf 4/,\$p\""
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

