如何用Sed转义多行字符串以在另一Sed命令中实现替换
解决多行字符串的sed转义与替换问题
你的核心问题在于原方案用echo处理多行字符串时会丢失换行符,而且sed默认是逐行处理文本的,直接用单行转义逻辑无法匹配多行模式。下面是针对多行场景优化后的完整解决方案:
关键改进点
- 用
printf替代echo来保留多行字符串的换行(echo会自动将换行转为空格,导致多行结构丢失) - 扩展转义规则,新增对换行符的转义(让sed能识别多行模式中的换行)
- 修改sed替换命令,先将整个文件读入模式空间,实现多行匹配替换
修正后的完整代码
#!/bin/bash # 定义专门处理多行字符串的sed转义函数 escape_sed_pattern() { local input="$1" # 1. 转义sed特殊字符:[]\/$*.^| # 2. 将换行符转义为\n(让sed能识别多行模式) printf "%s" "$input" | sed -e 's/[]\/$*.^|[]/\\&/g' -e ':a;N;$!ba;s/\n/\\n/g' } # 处理目标匹配字符串 read -r -d '' TARGET_STRING <<'HEREDOC' $N = "magic_quotes_gpc = <b>"._("On")."</b>"; $D = _("Increase your server security by setting magic_quotes_gpc to 'on'. PHP will escape all quotes in strings in this case."); $S = _("Search for 'magic_quotes_gpc' in your php.ini and set it to 'On'."); $R = ini_get('magic_quotes_gpc'); $M = TRUE; $this->config_checks[] = array("NAME" => $N , "DESC" => $D , "RESULT" => $R , "SOLUTION" => $S , "MUST" => $M ); HEREDOC ESCAPED_TARGET=$(escape_sed_pattern "$TARGET_STRING") # 处理替换字符串 read -r -d '' REPLACE_STRING <<'HEREDOC' /* NOTE: "Magic_quotes_gpc" is no longer required. We taught GOsa2 to deal with it (see /usr/share/gosa/html/main.php). By Questor */ /* Automatic quoting must be turned on */ /* $N = "magic_quotes_gpc = <b>"._("On")."</b>"; $D = _("Increase your server security by setting magic_quotes_gpc to 'on'. PHP will escape all quotes in strings in this case."); $S = _("Search for 'magic_quotes_gpc' in your php.ini and set it to 'On'."); $R = ini_get('magic_quotes_gpc'); $M = TRUE; $this->config_checks[] = array("NAME" => $N , "DESC" => $D , "RESULT" => $R , "SOLUTION" => $S , "MUST" => $M ); */ HEREDOC ESCAPED_REPLACE=$(escape_sed_pattern "$REPLACE_STRING") # 执行多行替换:先将整个文件读入模式空间,再执行替换 MODIFIED_STRING=$(sed -e ':a;N;$!ba;s/'"$ESCAPED_TARGET"'/'"$ESCAPED_REPLACE"'/g' file_name.txt) # 输出结果 echo "$MODIFIED_STRING"
代码解释
escape_sed_pattern函数:- 用
printf "%s"完整保留输入字符串的所有换行和空格 - 第一部分转义sed的特殊元字符(
[]\/$*.^|),确保这些字符被当作普通文本处理 - 第二部分
:a;N;$!ba是sed的多行读取技巧:循环读取所有行到模式空间,然后将换行符转义为\n,让sed能识别多行模式中的换行
- 用
sed替换命令:
:a;N;$!ba同样用于将file_name.txt的全部内容读入模式空间,这样sed就能匹配跨多行的目标字符串- 直接使用转义后的目标和替换字符串完成全局替换
移除原代码的单引号包裹逻辑:
- 用
printf替代echo后,不需要再用单引号包裹来保留首尾空格,因为printf会完整保留原始字符串的格式
- 用
内容的提问来源于stack exchange,提问作者Eduardo Lúcio
相关产品推荐
相关产品推荐

