这个问题与如何在文件第一行前插入文本?密切相关。我故意将标题设为与该问题相似以突出这一点。
除非目标文件是带有BOM的UTF-8。
因此,我想在文件的第一行中添加一个标题(0xef 0xbb 0xbf
字符)中包含 UTF-8 BOM 字节的文件。至少我这里的 UTF-8 带 BOM 文件以此开头。
如果我继续按照相关问题中的解决方案进行操作,
sed "1i My First line is now this." file.txt
我将得到类似这样的结果(在我的情况下是 VSCode)
My First line is now this.
?The first line was this one
Second line and so on
第二行的 UTF-8 字符用来?
表达一些不可打印的内容。
正如我们所料,另一个结果是文件不再以带 BOM 的 UTF-8 格式打开,我们现在依靠文本编辑器功能来“猜测”其编码。我们在项目中确定了一种模式,即使用带 BOM 的文件来确保所有内容都采用相同的编码。
如何在添加文本时保留文件中的 BOM 头?
从同一个相关问题中,一个答案为解决方案打开了大门:https ://unix.stackexchange.com/a/455250/413756
然后,通过对正则表达式选择组进行一些修改,我得到了这个表达式:
我得到了想要的结果,保留了文件中的 UTF-8 BOM 标头,甚至在最终与标头不匹配的文件中进行了替换。
如果你确定所有文件都是 BOM,那么这应该足够了:
请注意,这会专门捕获具有与我此处完全相同的标头的 UTF-8 BOM 文件。我相信不同的字节序列可能会发生在不同的格式中,这取决于每种情况 - 并且可能使用上述正则表达式(只需添加/替换
|\xXX\xYY\xZZ
或与选择组进行相应的匹配)。还要注意,在两个替换中,我假设文件的行尾只是
\n
(unix LF),而不是\r\n
(windows CRLF)。上述语法适用于 GNU Sed(Cygwin 以及可能大多数 Linux 发行版)。
UTF-8 BOM 非常不符合 Unix 风格,它很可能来自微软世界。然后行尾也可能是 CRLF 而不是 LF,甚至可能还有更多微软特质需要处理。如果您想使用 Unix/GNU 工具处理这些,您最好这样做:
对于就地编辑(此处使用 GNU 样式
-i
n 地编辑)或:动态处理(这里不需要
sed
)并将结果存储在新文件中(恢复为带有 BOM 的 Microsoft 格式)。另一种方法是使用
perl
(某些sed
实现从中复制了它们的-i
选项),并且File::BOM
除了 IO 层之外还使用该模块作为 IO 层:crlf
来处理 Microsoft 行尾:例子:
看到 BOM 移动到新行的开头并且第一行也用 CRLF 分隔。
为了能够处理具有 Microsoft 或 Unix 行结尾以及 UTF-8 BOM 或不具有 BOM 的文件,您可以执行以下操作:
在第一行(
$. == 1
),我们K
保留 BOM(如果有),然后插入换行符,后跟\r
如果在第一行末尾发现,则为\n
,然后是原始的第一行。如果文件最初是空的(没有 BOM),则不会插入新行,但随后不知道是否要添加以 Microsoft 或 Unix 行结尾的新行。