从字符串中删除除特定多字节范围之外的所有字符

从字符串中删除除特定多字节范围之外的所有字符

如何使用sed或另一种工具来删除所有字符除了特定的多字节范围?

例如,该范围\xd8\xa0 - \xd9\x8a涵盖以 UTF-8 编码的阿拉伯字符。这是我使用 sed 的天真而充满希望的尝试:

$ echo "Peace be upon you. السلام عليكم. שלום עליכם. Paz sobre vosotros." | sed -n -e 's|[^\xd8\xa0-\xd9\x8a]||p'
sed: -e expression #1, char 25: Invalid range end

理解sed了多字节字符,应该给我们留下字符串:

السلام عليكم

我考虑过使用iconv转换为一些阿拉伯语特定的编​​码,使用sed,然后转换回来。然而,我正在做的工作并不简单,例如我可能想保留阿拉伯语和希伯来语,因此如果可能的话,我希望始终将所有内容保留为 UTF-8。

如果sed无法使用多字节字符,我应该使用什么?我一直在寻找sed解决perl方案,但没有运气。

请注意,我尝试UTF-8向问题添加标签,但 unix.SE 将其更改为Unicode标签。这里没有 Unicode,这些是存储在磁盘上的编码字符串。我认为应该有一个单独的UTF-8标签。

答案1

您可以使用统一码属性在 Perl 中:

echo "Peace be upon you. السلام عليكم. שלום עליכם. Paz sobre vosotros." \
| perl -CIO -pe 's/\P{Arabic}//g'
  • -CIO告诉 Perl 输入和输出是 UTF-8 编码的。
  • \P{...}是一个负属性匹配,\p{...}将是一个正属性匹配。

答案2

使用(以前称为 Perl_6)

输入示例(OP 的文本保存为单行文件):

~$ cat peace.txt
Peace be upon you. السلام عليكم. שלום עליכם. Paz sobre vosotros.

提取阿拉伯文字:

~$ raku -ne 'put m:g/ <:Script<Arabic>>+ /;' peace.txt
السلام عليكم

提取希伯来语脚本:

~$ raku -ne 'put m:g/ <:Script<Hebrew>>+ /;' peace.txt
שלום עליכם

提取拉丁文字:

~$ raku -ne 'put m:g/ <:Script<Latin>>+ /;' peace.txt
Peace be upon you Paz sobre vosotros

Raku 为 Unicode 提供高级支持,并且它的正则表达式引擎已发展成为一个强大的“语法解析器”。请参阅下面的链接。请注意,如果不匹配,上面的代码将返回空行。如果您只想匹配元素/行,您可以简单地向$/(或) 匹配变量添加条件调用$<>

~$ cat peace2.txt #(remove terminal period from each phrase)
Peace be upon you
السلام عليكم
שלום עליכם
Paz sobre vosotros

~$ raku -ne 'put m:g/ <:Script<Latin>>+ /;' peace2.txt
Peace be upon you


Paz sobre vosotros

~$ raku -ne 'put $/ if m:g/ <:Script<Latin>>+ /;' peace2.txt
Peace be upon you
Paz sobre vosotros

最后,您可以通过插入字符来搜索 Unicode 属性的否定!。您还可以使用+和/或从所需的字符类中添加(甚至减去)-[注意:Z下面的附加正则表达式原子(空格)。为了完整起见,下面的代码显示了+!参数——尽管 a-在实践中可能有效]:

~$ raku -ne 'put $/ if m:g/ <+:!Script<Latin> + :!Z >+ /' peace2.txt
السلام عليكم
שלום עליכם

https://docs.raku.org/language/unicode
https://docs.raku.org/language/unicode#index-entry-UTF-8_Clean-8
https://stackoverflow.com/a/66540269/7270649

相关内容