sed - 用文件内容替换模式时的“未知命令”

问题描述

我尝试操作一些“模板化”文本文件。这意味着文件包含一些“标记”,需要用一些实际的字符串替换 - 要么是硬编码,要么是从其他文件中读取。

我有以下两行:

    sed -r -e 's_<!-- cssintern -->_<style type="text/css">\n<!-- cssintern -->\n</style>\n_' -i "$out_dir_aca/books_1by1/independent/$(basename "$aca_frag").html"
    sed -e '^<!-- cssintern -->^' -e '{r '"$src_dir_frags_struct/styles1.css.frag" -e 'd}' -i "$out_dir_aca/books_1by1/independent/$(basename "$aca_frag").html"

一个工作正常。问题是第二个产生了“未知命令”错误,我想不出如何修复它。调试输出如下(最后一行的错误文本):

+ for aca_frag in $out_dir_aca/frags_1by1/*
+ '[' -f '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag' ']'
++ basename '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
+ echo '    09.14 - Acatistul inaltarii Sfintei Cruci.frag'
    09.14 - Acatistul inaltarii Sfintei Cruci.frag
+ cat '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/1_txt_in/##_frags_struct_##/doctypeXHTML.frag'
++ basename '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
+ cat '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/1_txt_in/##_frags_struct_##/head.frag'
++ basename '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
+ cat '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/1_txt_in/##_frags_struct_##/foot.frag'
++ basename '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
++ basename '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
+ sed -r -e 's_<!-- cssintern -->_<style type="text/css">\n<!-- cssintern -->\n</style>\n_' -i '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/books_1by1/independent/09.14 - Acatistul inaltarii Sfintei Cruci.frag.html'
++ basename '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
+ sed -re '^<!-- cssintern -->^' -re '{r /home/vici/DropBox/MyFiles/work/___rug/_!_workarea/1_txt_in/##_frags_struct_##/styles1.css.frag' -re 'd}' -i '/home/vici/DropBox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/books_1by1/independent/09.14 - Acatistul inaltarii Sfintei Cruci.frag.html'
sed: -e expression #1,char 1: unkNown command: `^'

我使用分隔符 ^_/,我以“所有”方式使用简单和双引号,以及我在互联网上找到的所有其他内容错误仍然存​​在这一事实没有任何改变。

过去我用过这条线

sed.exe -i -e '/%%H/{r ..\/##_frags_##\/out\/%%H' -e 'd}' .\out\out.frag

在 Windows cmd 脚本中,并且运行良好。 (%%H 引用文件名,当解析文件夹中的所有文件时,带有 for)。我实际上是在 Linux 中重写旧脚本,作为练习 - 希望增加简单性和额外功能

我打算修改以下 sed 命令:

sed -e '/<TEXT1>/{r File1' -e 'd}' -i File2

满足我的特殊需求。

注意:我提供了确切的文件名和路径,认为它们可能会提供一些见解。

注意:我在虚拟机中使用 Debian 10.7。

注意:脚本文件#!/bin/bash -xv 开头。 -xv 显然只在调试时使用,否则会丢失。

解决方法

The syntax is(评论我的):

[2addr] {editing command       # No newline between '[2addr]' and '{'!
editing command
...
}

其中 [2addr] 是例如 /filtering/ 表达式。选项 -e 确实(强调我的):

如果指定了任何 -e 或 -f 选项,则编辑命令的脚本最初应为空。每个 -e 或 -f 选项指定的命令应按指定的顺序添加到脚本中。每次添加时,如果前一次添加(如果有)来自 -e 选项,则应在新添加之前插入 。生成的脚本应具有与操作数部分中描述的脚本操作数相同的属性。

[2addr]{ 之间有换行符时,脚本无效:

$ sed -e '/something/' -e '{' -e '}' /dev/null
sed: -e expression #1,char 11: missing command
$ sed '
/something/
{
}' /dev/null
sed: -e expression #1,char 13: unknown command: `
'

{[2addr] 放在一起可以解决问题,因为它删除了换行符:

$ sed -e '/somethimg/{' -e '}' /dev/null

所以把它和过滤表达式放在一起:

sed
   -e '\^<!-- cssintern -->^{'
   #   ^^                  ^^ here '{' is with /expression/
   # or just: -e '/<!-- cssintern -->/{'
   -e 'r blabla/styles1.css.frag'
   -e d
   -e '}' -i 'blabla/12.17 - Acatistul Sfantului Proroc Daniel.frag.html'

应该没问题。