我有很多 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 f
telfind
以仅返回纯文本文件 - 否则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 ® 正则表达式语法。