我有一个如下所示的文本文件:
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 only
和Also 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]
,只要我们使用C
或POSIX
区域设置。
这是一个应该可靠的命令:
LC_ALL=C sed -r ':a;N;s|^([\d0-\d127]+)\n([\d0-\d127]+)$|\1 / \2|;ta' file
笔记
LC_ALL=C
C
仅对此命令使用区域设置(否则会出现错误)-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 1
line 2
\1 / \2
第一行和第二行,用/
而不是换行符分隔。ta
- 如果最后一个搜索和替换命令成功,则再次执行循环。这使我们能够处理文件的所有行,并处理任何存在两个以上全 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 日本語
日本語のみ