blu*_*oon 59
如果你想使用Perl,那就这样做:
perl -pi -e 's/[^[:ascii:]]//g' filename
Run Code Online (Sandbox Code Playgroud)
详细说明
以下解释涵盖了上述命令的每个部分,假设读者不熟悉解决方案中的任何内容......
perl
运行perl解释器.Perl是一种编程语言,通常可在所有类似unix的系统上使用.此命令需要在shell提示符下运行.
-p
该-p标志告诉perl迭代输入文件中的每一行,在每一行上运行指定的命令(稍后描述),然后打印结果.它相当于包装你的perl程序while(<>) { /* program... */; } continue { print; }.有一个类似的-n标志同样但省略了continue { print; }块,所以你要使用它,如果你想自己打印.
-i
该-i标志告诉perl输入文件将在适当的位置进行编辑,输出应该返回到该文件中.这对于实际修改文件很重要.省略此标志将写入输出,STDOUT然后您可以将其重定向到新文件.
请注意,您不能省略-i并重定向STDOUT到输入文件,因为这会在读取之前破坏输入文件.这就是shell的工作方式,与perl无关.该-i标志解决了这个聪明.
Perl和shell允许您将多个单个字符参数组合成一个,这就是我们可以使用-pi而不是-p -i
该-i标志采用单个参数,如果要对原始文件进行备份,则使用该文件扩展名,因此如果您使用-i.bak,则perl会filename.bak在进行更改之前将输入文件复制到该文件.在这个例子中,我省略了创建备份,因为我希望你无论如何都会使用版本控制:)
-e
该-e标志告诉perl下一个参数是一个封装在字符串中的完整perl程序.如果你有一个非常长的程序,这并不总是一个好主意,因为它可以变得难以理解,但是如我们所拥有的单个命令程序,它的简洁性可以提高易读性.
请注意,我们不能将-e标志与-i标志组合在一起,因为它们都接受一个参数,而perl会假设第二个标志是参数,因此,例如,如果我们使用-ie <program> <filename>,perl将假设<program>并且<filename>都是输入文件和尝试创建<program>e并<filename>e假设这e是您要用于备份的扩展.这将失败,因为<program>它不是一个真正的文件.另一种方式(-ei)也不会工作,因为perl会尝试i作为程序执行,这将导致编译失败.
s/.../.../
This is perl's regex based substitution operator. It takes in four arguments. The first comes before the operator, and if not specified, uses the default of $_. The second and third are between the / symbols. The fourth is after the final / and is g in this case.
$_在我们的代码中,第一个参数是$_perl中的默认循环变量.如上所述,该-p标志包含我们的程序while(<>),它创建一个while循环,<>从输入一次读取一行().它隐式地指定了这一行$_,如果没有指定,所有接受单个参数的命令将使用它(例如:只是调用print;实际上会转换为print $_;).因此,在我们的代码中,s/.../.../运算符在输入文件的每一行上运行一次.
[^[:ascii:]]第二个参数是要在输入字符串中搜索的模式.此模式是正则表达式,因此其中包含的任何内容[]都是括号表达式.这部分可能是本例中最复杂的部分,因此我们将在最后详细讨论它.
<empty string> 第三个参数是替换字符串,在我们的例子中是空字符串,因为我们要删除所有非ascii字符.
g第四个参数是替换运算符的修饰符标志.该g标志指定替换在输入中的所有匹配项中应该是全局的.如果没有此标志,则只替换第一个实例.其他可能的标志i用于不区分大小写的匹配,s并且m仅与多行字符串相关(我们这里有单行字符串),o它指定应该预编译模式(这对于长文件可能很有用),并x指定该模式可以包含空格和注释,以使其更具可读性(但如果是这种情况,我们不应该在一行上编写我们的程序).
filename
这是包含我们想要删除的非ascii字符的输入文件.
[^[:ascii:]]
现在让我们[^[:ascii:]]更详细地讨论一下.
如上所述,[]在正则表达式中指定括号表达式,该表达式告诉正则表达式引擎匹配输入中与表达式内字符集中的任何一个字符匹配的单个字符.因此,例如,[abc]将匹配aa b或a或a c,它将仅匹配单个字符.使用^的第一个字符反转的比赛,因此[^abc]将匹配任何一个字符不是一个a,b或c.
但是[:ascii:]在括号表达式中呢?
如果您有基于unix的系统,请man 7 re_format在命令行运行以阅读手册页.如果没有,请阅读在线版本
[:ascii:]是一个表示整个ascii字符集的字符类,但是这种字符类只能在括号表达式中使用.使用[[:ascii:]]它的正确方法是,它可以像abc上面的情况一样被否定,或者在括号表达式中与其他字符组合,因此,例如,[éç[:ascii:]]将匹配所有ascii字符é以及ç哪些不是ascii,并且[^éç[:ascii:]]将匹配所有字符这不是ascii,也不是é或ç.
tr -dc [:graph:][:cntrl:] < input-file > cleaned-file
Run Code Online (Sandbox Code Playgroud)
这是假设你想保留"控制"字符和"可打印"字符.根据需要提琴.