Powershell在文本文件中查找非ASCII字符

Aro*_*lix 8 powershell non-ascii-characters

我正在尝试找到一种使用 Powershell 脚本执行以下操作的方法。

\n\n
    \n
  1. 对于文本文件中的每一行,检查该行是否包含非 ASCII 字符
  2. \n
  3. 如果行包含非 ASCII 字符,则输出到单独的文件
  4. \n
  5. 如果该行不包含非 ASCII 字符,则跳到下一行
  6. \n
\n\n

我所说的非 ASCII 字符是指非键盘字符,例如重音字符、其他语言的字符等。

\n\n

样本数据

\n\n
 - \xe5\xbc\xa0\xe4\xbc\x9f\n - \xe0\xae\x95\xe0\xaf\x81\xe0\xae\xb4\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xaf\x88\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x81\xe0\xae\x95\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xbe\xe0\xae\xa9 \xe0\xae\xaa\xe0\xaf\x86\xe0\xae\xaf\xe0\xae\xb0\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x8d\n - \xe6\x97\xa5\xe6\x9c\xac\xe4\xba\xba\xe3\x81\xae\xe6\xb0\x8f\xe5\x90\x8d\n - Full Name\n - L\xc3\xa9na R\xc3\xa9mi\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出数据

\n\n
 - \xe5\xbc\xa0\xe4\xbc\x9f\n - \xe0\xae\x95\xe0\xaf\x81\xe0\xae\xb4\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xaf\x88\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x81\xe0\xae\x95\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xbe\xe0\xae\xa9 \xe0\xae\xaa\xe0\xaf\x86\xe0\xae\xaf\xe0\xae\xb0\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x8d\n - \xe6\x97\xa5\xe6\x9c\xac\xe4\xba\xba\xe3\x81\xae\xe6\xb0\x8f\xe5\x90\x8d\n - L\xc3\xa9na R\xc3\xa9mi\n
Run Code Online (Sandbox Code Playgroud)\n\n

我在其他线程中发现了正则表达式来删除非 ASCII 字符,但我似乎无法使其工作。

\n\n

请帮忙!

\n\n

** 编辑 **\n感谢大家的帮助!我已经成功地用下面的脚本做了我想做的事情。

\n\n
$nonASCII = "[^\\x00-\\x7F]"\nforeach ($_ in [System.IO.File]::ReadLines($source)){\n    if ($_ -cmatch $nonASCII){\n        write-output $_ | out-File $output -append        \n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Mat*_*sen 9

定义一个描述所有 ASCII 字符(代码点 32 到 127 == [\\x20-\\x7F])的字符集,然后使用 对其求反^以匹配任何非 ASCII 字符!

\n\n

让我们根据我的(非 ASCII)名字来测试一下:

\n\n
PS C:\\> \'Mathias R. Jessen\' -cmatch \'[^\\x20-\\x7F]\'\nFalse\nPS C:\\> \'Mathias R\xc3\xb8rbo Jessen\' -cmatch \'[^\\x20-\\x7F]\'\nTrue\n
Run Code Online (Sandbox Code Playgroud)\n\n

要过滤字符串列表,只需-cmatch在过滤模式下使用运算符:

\n\n
$strings = \'\xe0\xae\x95\xe0\xaf\x81\xe0\xae\xb4\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xaf\x88\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x81\xe0\xae\x95\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xbe\xe0\xae\xa9 \xe0\xae\xaa\xe0\xaf\x86\xe0\xae\xaf\xe0\xae\xb0\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x8d\', \'Boring John Doe\', \'L\xc3\xa9na R\xc3\xa9mi\'\n\n$nonASCIIstrings = @($strings) -cmatch \'[^\\x20-\\x7F]\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,如果您想沿管道过滤,请使用Where-Object

\n\n
$strings |Where-Object {$_ -cmatch \'[^\\x20-\\x7F]\'}\n
Run Code Online (Sandbox Code Playgroud)\n


mkl*_*nt0 5

\n

.NET 正则表达式引擎支持“非 ASCII 字符”概念的直接\\P{IsBasicLatin}表达:(相反,即“ASCII 字符”,是\\p{IsBasicLatin}):

\n
\' - \xe5\xbc\xa0\xe4\xbc\x9f\',\n\' - \xe0\xae\x95\xe0\xaf\x81\xe0\xae\xb4\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xaf\x88\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x81\xe0\xae\x95\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xbe\xe0\xae\xa9 \xe0\xae\xaa\xe0\xaf\x86\xe0\xae\xaf\xe0\xae\xb0\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x8d\',\n\' - \xe6\x97\xa5\xe6\x9c\xac\xe4\xba\xba\xe3\x81\xae\xe6\xb0\x8f\xe5\x90\x8d\',\n\' - Full Name\', \n\' - L\xc3\xa9na R\xc3\xa9mi\' -cmatch \'\\P{IsBasicLatin}\'\n
Run Code Online (Sandbox Code Playgroud)\n

IsBasicLatin是命名 (Unicode) 块的示例

\n

上面要求-cmatch, 的区分大小写-match, [1]则表达式匹配运算符至少包含一个非 ASCII 范围字符的输入行(数组元素):

\n
 - \xe5\xbc\xa0\xe4\xbc\x9f\n - \xe0\xae\x95\xe0\xaf\x81\xe0\xae\xb4\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xaf\x88\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x81\xe0\xae\x95\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xbe\xe0\xae\xa9 \xe0\xae\xaa\xe0\xaf\x86\xe0\xae\xaf\xe0\xae\xb0\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x8d\n - \xe6\x97\xa5\xe6\x9c\xac\xe4\xba\xba\xe3\x81\xae\xe6\xb0\x8f\xe5\x90\x8d\n - L\xc3\xa9na R\xc3\xa9mi\n
Run Code Online (Sandbox Code Playgroud)\n
\n

对于流解决方案- 逐行处理从文件中读取的行,您可以-matchWhere-Objectcmdlet 结合使用:

\n
Get-Content in.txt | \n  Where-Object { $_ -cmatch \'\\P{IsBasicLatin}\' } |\n  Set-Content -Encoding Utf8 out.txt\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,Get-Content用于逐行读取文件 - 虽然[System.IO.File]::ReadLines((Convert-Path in.txt))也可以,但仅在存在性能问题时才需要。

\n
\n

[1] 原因是,在不区分大小写的匹配中,小写 ASCIIik字符都被视为在ASCII 块内部外部,即\'i\' -match \'\\P{IsBasicLatin}\'\'i\' -match \'\\p{IsBasicLatin}\'都是 $true有关解释,请参阅此答案向js2010致敬。

\n