【问题标题】:sed replace line with multiline-variablesed 用多行变量替换行
【发布时间】:2014-11-20 08:59:17
【问题描述】:

我正在尝试用存储在变量中的多行字符串替换文件中的单行。

打印到屏幕时我能够得到正确的结果,但如果我想进行就地替换,则不能。

文件格式:

*some code*
*some code*
string_to_replace
*some code*

我希望生成的文件是:

*some code*
*some code*
line number 1
line number 2
line number 3
*some code*

我试过的代码是:

new_string="line number 1\nline number 2\nline number 3"

# Correct output on screen
sed -e s/"string_to_replace"/"${new_string}"/g $file

# Single-line output in file: "line number 1line number 2line number 3"
sed -i s/"string_to_replace"/"${new_string}"/g $file

尝试组合-i-e 选项时,结果与仅使用-i 时相同。

我在 CentOS 上使用 GNU sed 4.1.5 版(通过 Mac 的 ssh 连接到它)。

【问题讨论】:

  • 正如我的 [现已删除] 答案中所见,它是关于从 Windows 转换文件。为此,请检查dos2unix
  • Stack Overflow 是一个编程和开发问题的网站。这个问题似乎离题了,因为它与编程或开发无关。请参阅帮助中心的What topics can I ask about here。也许Super UserUnix & Linux Stack Exchange 会是一个更好的提问地点。
  • 你试过"${new_string//\n/\\n}"吗? Sed 需要\n 进行替换;文字换行符将开始下一个命令。

标签: bash sed multiline


【解决方案1】:

将多行字符串内联到 sed 脚本需要您转义任何文字换行符(以及任何文字 & 字符,否则会插入您要替换的字符串,当然还有任何文字反斜杠,以及您用作替换分隔符的任何字符)。究竟什么会起作用也稍微取决于精确的sed 方言。最终,这可能是使用 sed 以外的其他东西更健壮和便携的情况之一。但是尝试例如

sed -e 's/[&%\\]/\\&/g' \
    -e '$!s/$/\\/' \
    -e '1s/^/s%string_to_replace%/' \
     -e '$s/$/%g/' <<<$replacement |
# pass to second sed instance
sed -f - "$file"

&lt;&lt;&lt;"here string" 语法是 Bash 特有的;你可以用printf '%s\n' "$replacement" | sed替换它。

并非所有sed 版本都允许您使用-f - 在标准输入上传递脚本。也许尝试用/dev/stdin/dev/fd/0 替换单独的破折号;如果这也不起作用,您必须将生成的脚本保存到临时文件中。 (Bash 允许您使用命令替换 sed -f &lt;(sed ...) "$file",这非常方便,并且在您完成后不必删除临时文件。)

演示:https://ideone.com/uMqqcx

【讨论】:

    【解决方案2】:

    尽管您已明确要求使用 sed,但您可以使用 awk 完成此操作,方法是将您的多行变量存储在文件中,使用以下内容

    awk '/string_to_replace/{system("cat file_with_multiple_lines");next}1' file_to_replace_in > output_file
    

    【讨论】:

    • 使用cat 的子进程很方便,但效率很低。如果您发现自己经常这样做,不妨将其重构为使用常见的NF==FNR Awk 习惯用法将文件读入内存,然后处理后续文件。
    【解决方案3】:

    sed 中,您可以将命令字符串双引号并让shell 为您进行扩展,如下所示:

    new_string="line number 1\nline number 2\nline number 3"
    sed -i "s/string_to_replace/$new_string/" file
    

    【讨论】:

    • 这仅适用于 sed dialetcts,它将转义码 \n 扩展为文字换行符;这种行为不是标准的或可移植的。
    猜你喜欢
    • 1970-01-01
    • 2011-10-04
    • 2019-03-24
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 2022-01-19
    • 2013-09-14
    相关资源
    最近更新 更多