sed:在节末尾之前插入文本

sed:在节末尾之前插入文本

我需要在该部分末尾之前将一些文本插入到 HTML 文件中HEAD

我想:

sed -i "s#</head>#<style> @page { prince-shrink-to-fit: auto }
.repository-with-sidebar.with-full-navigation .repository-content 
{width: 950px ! important;} </style>\n</head>#" ${1}"/"${2}"/"${i}.html

我收到错误:

sed: 1: command a expects \ followed by text

我只是没有看到我的错误。我什至尝试在样式周围使用单引号。

我想在该部分末尾之前插入的确切文本HEAD是:

<style>
@page { prince-shrink-to-fit: auto }
.repository-with-sidebar.with-full-navigation .repository-content 
{width: 950px ! important;}
</style>

编辑:这是确切的命令:

sed -i "s#</head>#<style> @page { prince-shrink-to-fit: auto } .repository-with-sidebar.with-full-navigation .repository-content {width: 950px ! important;} </style>\n</head>#" ${1}"/"${2}"/"${i}.html

编辑2:为了尝试并确保我正确地格式化了命令,我也在尝试这样做:

strToInsert='<style> @page { prince-shrink-to-fit: auto } .repository-with-sidebar.with-full-navigation .repository-content {width: 950px ! important;} </style>'

sed -i "s#</head>#$strToInsert\n</head>#" ${1}"/"${2}"/"${i}.html

这让我意识到我插入的文本可能有问题。

答案1

In-placesed过程中需要制作备份文件。这-iApple 上的选项sed需要扩展参数(对于它创建的备份文件)并使用下一个参数。这意味着您告诉它您希望它创建一个扩展名为“ #s</head>#...”的备份文件。

该错误意味着它认为您指的是a挂起命令。我猜测 的值$1以 开头a。因为-iate 前面的参数sed认为这是要运行的脚本,而不是要更改的文件的路径,因此您会收到相应的错误。这正是您在 Applesed和无效a命令时会遇到的错误:

$ sed a
sed: 1: "a": command a expects \ followed by text

-i在命令中提供扩展参数sed

sed -i.bak "s#</head>#<style> @page { prince-shrink-to-fit: auto } .repository-with-sidebar.with-full-navigation .repository-content {width: 50px ! important;} </style>\n</head>#" "${1}/${2}/${i}.html"

并且事情会起作用(尽管请注意这\n不是换行符转义)。如果使用单引号,甚至可以去掉“”中的空格!important

sed上面的代码也适用于 GNU ,但请注意-i不是 POSIX 选项并且一般不便于携带。

通常建议无论如何都不要使用就地修改,并自己明确地处理文件副本。不过,这取决于你。


您应该引用变量扩展${1}等。仅引用斜杠是没有意义的,因为它们始终是文字。

答案2

我很抱歉,但读了你的声明我想在 HEAD 部分末尾插入的确切文本是......让我最初相信我们正在讨论将文本附加到文件部分而不是之前插入 - 所以我首先写了这个答案。在重新阅读问题并更仔细地研究您的示例sed命令之后 - 我想我明白这实际上是在匹配之前插入文本。所以这个答案现在也在这里 - 您将在下面找到执行任一操作的说明。

要安全地将任意字符串i插入或附加到行的头部/尾部,您有几个选项,每个选项都比上一个更复杂。ased

第一个也是最简单的一个是read 命令。它需要零转义。例如,如果您要附加的字符串位于文件中,./append您可以执行以下操作:

sed '\|</head>|r ./append' <infile >outfile

或者插入它在匹配的过程中,您可以在打印之前将其匹配一个周期,并带有一点前瞻功能,例如:

sed -e '$!N;\|\n</head>|r ./insert' -e 'P;D' <infile >outfile

read 被指定写入标准输出 - 我不确定这将如何与-inplace 选项一起工作(无论如何,在我看来,这主要是一个丑陋的黑客行为)。我认为sed应该做与print 相同的事情,并将 stdout 重定向到其命名的-inplace 编辑文件。

另一种选择是使用apend 命令 - for追加那是。为了安全地做到这一点,你只需要转义\n行和反斜杠。你可以这样做:

printf %s\\n "$str_to_append" |
sed 's|\\|&&|g;$!s|$|\\|;1i\
    \\|</head>|a\\' |
sed -f - infile >outfile

a不过, pend 的行为被指定为read 的行为,因此我再次不确定它在-in-place hack 中的行为如何。

如果您将a\\上面替换为 w/ ,i\\它将把i文本插入到标准输出(或命名为-inplace edit-file - 如果这适用于您的实现) 模式空间被写出。

如果你喜欢额外的工作,(或者,在我能想到的唯一实际用途中,您按特定顺序在每行安排多个reads/ pends)a它也可以用于插入,就像我r之前使用 ead 所做的那样:

printf %s\\n "$str_to_append" |
sed 's|\\|&&|g;$!s|$|\\|;1i\
    \\|\\n</head>|a\\' |
sed -e '$!N' -f - -e 'P;D' infile >outfile

我提供的最后一个几乎是相同的,除了你还必须逃脱&分隔符 (通常是/。它可以这样工作:

printf %s\\n "$str_to_append" |
sed 's|[\/&]|\\&|g
   $!s|$|\\|;$s|$|/|
     1i\
     /<\\/head>/s/^/\\' |
sed -f - infile >outfile

这将影响插入 -如果您希望以这种方式附加字符串,您只需将 a^与 a交换即可。$

-i我相当有信心无论您是否添加该选项都会起作用。

-i最后一点,您也可以这样做,而不是使用:

sed '$d;\|</head>|r ./append' <<IN >infile
$(   cat <infile; echo .)
IN

...或者,对于插入:

sed -e '$d;N;\|\n</head>|r ./insert' -e 'P;D' <<IN >infile
$(   cat <infile; echo .)
IN

...这将得到你的内菲莱就地编辑,没有任何可能-i影响的意外权限问题。

相关内容