SED替换问题:指定token后单次替换word1为word2失败求助
问题需求
需要在目标字符串中找到标记3后,将紧随其后的第一个off替换为on。
现有代码
PARAM="0 \" 0 - ${TEXT0}\" off 1 \" 1 - ${TEXT1}\" off 2 \" 2 - ${TEXT2}\" off 3 \" 3 - ${TEXT3}\" off 4 \" 4 - ${TEXT4}\" off 5 \" 5 - ${TEXT5}\" off 6 \" 6 - ${TEXT6}\" off 7 \" 7 - ${TEXT7}\" off 8 \" 8 - ${TEXT8}\" off 9 \" 9 - ${TEXT9}\" off 10 \" 10 - ${TEXT10}\" off 11 \" 11 - ${TEXT11}\" off 12 \" 12 - ${TEXT12}\" off 13 \" 13 - ${TEXT13}\" off 14 \" 14 - ${TEXT14}\" off 15 \" 15 - ${TEXT15}\" off 16 \" 16 - ${TEXT16}\" off 17 \" 17 - ${TEXT17}\" off 18 \" 18 - ${TEXT18}\" off 19 \" 19 - ${TEXT19}\" off" CUR_PARAM=${PARAM} NEW_PARAM=$(echo ${CUR_PARAM} | sed -e '/3/ s/off/on/')
当前执行结果
" 0 - Exit" on 1 " 1 - ..............
预期结果
0 " 0 - Exit" off 1 " 1 - RUN_INITIAL_TASK" off 2 " 2 - (N.I.U) FORBID REF LEAP SERVICE" off 3 " 3 - INSTALL MY REF LEAP SERVICE" on 4 " 4 - INSTALL SUDOERS" off 5 " 5 - INSTALL SET LOCALE" off 6 " 6 - REMOVE PACKAGE and SET LOCK" off 7 " 7 - INSTALL MY MINI SYS CONFIG" off 8 " 8 - INSTALL JOURNALD CONFIG" off 9 " 9 - INSTALL PAM.D CONFIG" off 10 " 10 - INSTALL MY BASH FUNCTIONS" off 11 " 11 - INSTALL KERNEL HEADERS and COMPILING TOOLS" off 12 " 12 - INSTALL SSH" off 13 " 13 - INSTALL PUTTY" off 14 " 14 - INSTALL BROTHER PRINTER" off 15 " 15 - INSTALL HPLIP PRINTER" off 16 " 16 - CONFIGURE FIREWALLD" off 17 " 17 - INSTALL VIRTUALBOX HOST MODE 1" off 18 " 18 - INSTALL VIRTUALBOX HOST MODE 2" off 19 " 19 - INSTALL VIRTUALBOX VM GUEST" off
问题分析
- 字符串展开破坏格式:
echo ${CUR_PARAM}未用双引号包裹变量,导致shell解析时丢失引号、打乱空格结构,输出内容已损坏。 - sed替换逻辑错误:原命令
/3/ s/off/on/会匹配整个包含3的行,然后替换该行第一个off(即token 0后的off),而非token 3后的目标off。
解决方案
修正后的完整代码
PARAM="0 \" 0 - ${TEXT0}\" off 1 \" 1 - ${TEXT1}\" off 2 \" 2 - ${TEXT2}\" off 3 \" 3 - ${TEXT3}\" off 4 \" 4 - ${TEXT4}\" off 5 \" 5 - ${TEXT5}\" off 6 \" 6 - ${TEXT6}\" off 7 \" 7 - ${TEXT7}\" off 8 \" 8 - ${TEXT8}\" off 9 \" 9 - ${TEXT9}\" off 10 \" 10 - ${TEXT10}\" off 11 \" 11 - ${TEXT11}\" off 12 \" 12 - ${TEXT12}\" off 13 \" 13 - ${TEXT13}\" off 14 \" 14 - ${TEXT14}\" off 15 \" 15 - ${TEXT15}\" off 16 \" 16 - ${TEXT16}\" off 17 \" 17 - ${TEXT17}\" off 18 \" 18 - ${TEXT18}\" off 19 \" 19 - ${TEXT19}\" off" CUR_PARAM=${PARAM} # 保留原字符串格式,精准替换token3后的第一个off NEW_PARAM=$(echo "${CUR_PARAM}" | sed -E 's/(3 ".*?") off/\1 on/')
关键修正点
- 保留字符串结构:用
echo "${CUR_PARAM}"替代echo ${CUR_PARAM},双引号包裹变量可保留原有的引号和空格布局。 - 精准匹配替换:
sed -E启用扩展正则,简化语法(3 ".*?")捕获token3对应的3 "..."部分,.*?是非贪婪匹配,确保只匹配到token3的描述内容- 将捕获内容后的
off替换为on,实现目标位置的精准修改
若系统不支持扩展正则,可改用基础正则版本:
NEW_PARAM=$(echo "${CUR_PARAM}" | sed 's/\(3 "[^"]*"\) off/\1 on/')
内容的提问来源于stack exchange,提问作者jcdole
相关产品推荐
相关产品推荐

