将文本文件限制为某个字长,但保留完整的句子

时间:2015-08-03 06:47:27

标签: bash machine-learning nlp feature-selection normalize

我有一个我需要复制的文本文件集,但是在保持完整句子的同时将每个文件限制为大致相同的单词长度。将{.?!}内的任何标点符号视为句子边界是可以接受的。我可以用python做到这一点,但我正在尝试学习bash,所以欢迎提出建议。我一直在考虑的方法是将目标字长超过几个字,然后将结果修剪到最后一个句子边界。

我熟悉headwc,但我无法想出将两者结合起来的方法。 man的{​​{1}}文件未指明使用字数的方法,head的{​​{1}}文件未指明分割文件的方法。

上下文: 我正在开发一个带有机器学习的文本分类任务(使用man作为记录)。我想确保文本长度(在我的数据中变化很大)不会过多地影响结果。为此,我尝试在执行特征提取之前规范化文本长度。

1 个答案:

答案 0 :(得分:2)

让我们考虑一下这个测试文件:

$ cat file
Do I exist? I program. Therefore, I am!

假设我们要截断此文件以完成20个字符或更少的句子:

$ awk -v n=20 -v RS='[.?!]' '{if (length(s $0 RT)>n) exit; else s=s $0 RT;} END{print s;}' file
Do I exist?

如果我们想要30个字符或更少:

$ awk -v n=30 -v RS='[.?!]' '{if (length(s $0 RT)>n) exit; else s=s $0 RT;} END{print s;}' file
Do I exist? I program.

如何运作

  • -v n=20

    这会将awk变量n设置为我们想要的最大长度(不包括文件的最终换行符)。

  • -v RS='[.?!]'

    这会将awk记录分隔符RS设置为您提到的三个字符中的任何一个。

  • if (length(s $0 RT)>n) exit; else s=s $0 RT

    对于文件中的每条记录(记录是句子),我们测试是否将其添加到s会使输出太长。如果它使输出太长,那么我们退出。如果没有,我们会将其添加到s

    在awk中,$0表示完整记录,RT是awk在记录末尾找到的记录分隔符。

  • END{print s;}

    在退出之前,会打印字符串s

备选1:根据单词数

截断

假设我们想要根据单词的数量进行截断。如果我们想要,例如,6个字:

$ awk -v n=6 -v RS='[[:space:]]+' 'NR>n{exit;} {printf "%s%s",$0,RT;} END{print"";}' file
Do I exist? I program. Therefore, 

不同之处在于我们知道使用空格作为记录分隔符。通过这种方式,每个记录都是一个单词并保持打印单词,直到达到极限。

备选方案2:整句但词数有限

$ awk -v n=6 -v RS='[.?!]' '{c+=NF; if (c>n) exit; else s=s $0 RT;} END{print s;}' file
Do I exist? I program.

Mac OSX

上面将记录分隔符RS设置为正则表达式。这可能需要GNU awk(gawk)。 OSX man page for awk未说明是否支持此功能。但是,@ bebop报告说,从macports安装gawk后,上述代码可以在OSX上成功运行。