如何在 Ubuntu 中更改许多文件中的 ^L 代码?

如何在 Ubuntu 中更改许多文件中的 ^L 代码?

我有很多 XML 文件,超过 50000 个。

在一些XML文件中,有些文件是这样写的

<filename>abc.JPEG<^Lilename>

^L只是一个字符,但我无法^L用谷歌找到它的意思。

当我使用cat打印文件内容时,它显示如下

<filename>abc.JPEG<
                   ilename>

无论如何,我想<filename>abc.JPEG<^Lilename>换成<filename>abc.JPEG</filename>

我已经找到了一些可以在许多文件中更改单词的命令,例如

find . -exec perl -pi -e 's/[find_word]/[change_word]/g' {} \;

但是对我来说该命令不起作用,因为当我输入时它无法识别搜索词^L

我怎样才能在多个文件中<filename>abc.JPEG<^Lilename>进行更改?<filename>abc.JPEG</filename>

答案1

Control-L(表示为^L)是“换页符”。在 ASCII 中,它的十进制值为 12(L是字母表的第 12 个字母)或十六进制值 0c:

$ printf 'foo\x0cbar\n' | cat -et
foo^Lbar$

$ printf 'foo\x0cbar\n'
foo
   bar

您可以使用 sed 之类的工具通过指定十六进制转义码来替换它:

$ printf 'foo\x0cbar\n' | sed 's/\x0c//'
foobar

或者,^L直接使用键盘序列CTRL++V CTRLL

sed 's/CTRL+VCTRL+L//'

对于您的具体替换,给出

$ printf '<\x0cilename\n'
<
 ilename

然后

$ printf '<\x0cilename\n' | sed 's/<\x0c/<\/f/g'
</filename

g如果每行有多个实例,则添加修饰符)。

答案2

正如 Hans-Martin Mosner 在评论中指出的那样,似乎有人在生成 XML 时使用了反斜杠而不是正斜杠(或者可能将整个<filename>部分通过了对斜杠过于热衷的 Unix-to-Windows 转换器)。是一个很少使用的换页符转义序列,又名 U+0C 或 ^L。因此,管道的后续步骤随后用文字 U+0C 字符\f替换了。\f

幸运的是,U+0C 是一个极其罕见的字符,不太可能被发现故意地在任何 XML 中。由于只会\f生成此内容,而不是(例如)\g\k,因此通用查找和替换不仅应修复,</filename>还应修复</folder></file>或任何其他损坏的内容。

这就是 steeldriver 的 sed 脚本所做的;我只是让它更通用一些:

sed 's|\x0c|/f|g'

这意味着“(s)将所有\x0c(即,U+0C)实例/f全局地替换为 ”。

答案3

\f是 Perl 中的换页符。看起来这些格式错误的文件是由刚接触 Perl 和 XML 的人创建的。

这是一个 Perlier 修复程序 - 它也满足 OP 自动更新所有文件的目标,这与使用 sed 接受的答案不同,因为它没有与 配对,所以它一次只能对一个文件起作用find

\f可以简单地用来代替十六进制代码x0c

find . -type f -exec perl -pi.bkp -e 's [ \f ilename ][ /f ilename ]gx' {} \;

在这里我添加了-type ftelfind以仅返回纯文本文件 - 否则find将返回.列表中,并在您尝试编辑它时触发警告,但其他一切仍将有效。

我还通过使用x忽略真实空格的标志使正则表达式更容易被看到,允许您将正则表达式的元素隔开。如果您不喜欢这个,下面是没有这个标志的版本:

find . -type f -exec perl -pi.bkp -e 's[\filename][/filename]g' {} \;

并且很可能所有的换页符都是伪造的并且都应该被替换/f,那么您可以进一步精简一行代码:

find . -type f -exec perl -pi.bkp -e 's[\f][/f]g' {} \;

在 Perl 中,您不需要使用正斜杠来括住正则表达式替换命令的元素 ( s///)。您可以使用任何符号。但是,如果您选择使用任何类型的成对括号符号,则必须同时使用它们:s[old][new]例如。

由于我没有使用斜线,因此我不需要转义任何斜线。

至于-i.bkp:perl -pi -e可让您就地编辑 - 但如果您想在查找和替换 Perl 程序出错的情况下获得额外的保险,您可以输入文件扩展名,以便它为您复制原始文件。在这里,我使用了.bkp

在最新版本的 Perl 中,就地编辑已更新为更具弹性,以防您的系统遇到断电或磁盘空间不足等严重问题。以下是 Perl 作者 brian d foy 对近期 Perls 中改进的就地编辑的评论。

您应该考虑使用 Perl 来执行这些类型的任务,因为它是一种非常强大但被低估的通用编程语言,其最初的设计目标之一就是用更好的语言来替代sed它。awk

Perl 5 的正则表达式匹配能力和改进的正则表达式语法远远超过了sed、,awk甚至超过了除 Perl 6 之外的所有其他编程语言,这使得 Perl 成为简单和高级正则表达式操作的最明智选择。

需要澄清的是:也sed可以使用find,您还可以使用sed -i.bkp来备份每个编辑的文件,但据我所知,它不具备 Perl 5.28 及更高版本中的额外弹性。它还使用了更笨重且功能远不够强大的传统 UNIX ® 正则表达式语法。

相关内容