如何在文件中搜索仅包含 ASCII 字符的行然后对其采取操作?

如何在文件中搜索仅包含 ASCII 字符的行然后对其采取操作?

我有一个如下所示的文本文件:

English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ
English words only
Also English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ

请注意,在中间,有两条线,English words onlyAlso English words only,一条紧挨着一条。

我需要做的是把这两行合并为一行,并用 分隔/,如下所示:

English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ
English words only / Also English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ

我发现我可以使用以下正则表达式搜索包含 ASCII 字符的行,[[:ascii:]]并使用搜索非 ASCII 字符[^[:ascii:]]。但是,我在使用正则表达式查找以下实例时遇到了一些麻烦不是匹配条件,因为我需要搜索的是行没有非 ASCII 字符。

我发现关于“逆向匹配”的问题,但是,那里的答案超出了我的理解范围。

当然,根据线条之间的关系来匹配线条又是另一个问题。当这些线条是一条接一条时,我可以匹配它们吗?我甚至不确定这是否可行。

有没有什么方法可以使用 LibreOffice、Gedit 或命令行搜索所有没有非 ASCII 字符的行,然后将它们组合起来?

请注意,该文件有数千行长,而且我也不确定,但它可能有可能出现 3 到 4 条一组的纯英语台词。

答案1

似乎您可以使用它sed来完成这项工作,即使它不知道[[:ascii:]]字符类。相反,我们可以用一系列的 ASCII 字符来指定转义序列 [\d0-\d127],只要我们使用CPOSIX区域设置。

这是一个应该可靠的命令:

LC_ALL=C sed -r ':a;N;s|^([\d0-\d127]+)\n([\d0-\d127]+)$|\1 / \2|;ta' file

笔记

  • LC_ALL=CC仅对此命令使用区域设置(否则会出现错误)
  • -r使用扩展的正则表达式使命令更具可读性(我们需要更少的反斜杠)(GNUsed也识别-E相同的含义)。
  • :a标签 - 循环从这里开始
  • ;分隔命令,就像在 shell 中一样
  • N将下一行读入模式空间,以便我们可以替换\n
  • s|old|new|old用。。。来代替new
  • ^([\d0-\d127])\n([\d0-\d127]+)$- 仅用 ASCII 匹配两行并捕获 中的第一行\1和 中的第二行\2^是行首,\n是换行符,$是行尾,因此测试和 的^line 1\nline 2$全部。line 1line 2
  • \1 / \2第一行和第二行,用 / 而不是换行符分隔。
  • ta- 如果最后一个搜索和替换命令成功,则再次执行循环。这使我们能够处理文件的所有行,并处理任何存在两个以上全 ASCII 行的情况。

非常感谢伊莱亚·卡根为了向我展示如何使用转义序列匹配 ASCII 字符

答案2

如果你想整行仅由 ASCII 字符组成,您需要将模式锚定到行的开始和结束,例如grep

$ grep -P '^[[:ascii:]]*$' file
English words only
English words only
English words only
Also English words only
English words only

一些工具提供了整行标志,例如 grep-x--line-regexp

   -x, --line-regexp
          Select  only  those  matches  that exactly match the whole line.
          For a regular expression pattern, this  is  like  parenthesizing
          the pattern and then surrounding it with ^ and $.

允许您使用:

$ grep -Px '[[:ascii:]]*' file
English words only
English words only
English words only
Also English words only
English words only

多行匹配增加了另一层复杂性,因为许多常见的命令行文本处理实用程序都是基于行的。您可以grep使用标志强制读取整个文件,但是此时-Z诸如pcregrep或本身之类的工具可能更合适。perl

下一个您需要解决的问题是如何在多行匹配的上下文中解释“行首”和“行尾”的概念。有些工具提供了相关标志,如正则表达式教程:锚点:perl就是其中之一,它提供了一个/m修饰符。您仍然需要通过取消设置默认记录分隔符来提取文件(此处使用 完成-0777);例如

$ perl -0777 -pe 's{^([[:ascii:]]+)\n([[:ascii:]]+)$}{$1 / $2}mg' file
English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ
English words only / Also English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ

相关内容