【问题标题】:Awk split pattern error: empty line splits in the middle of a lineawk拆分模式错误:空行在一行中间拆分
【发布时间】:2020-11-10 17:45:41
【问题描述】:

我正在尝试将一个大文本文件 (10Gb+) 拆分为固定 # 的空行,并建议使用单行 here:

awk 'BEGIN {nParMax = 100000; npar = 0 ;nFile =0}
     /^$/{npar++;if(npar==nParMax){nFile++;npar=0;next}}
     {print $0 > "split_"nFile".out"}'  fname

它可以在 99.99% 的时间内完成工作,这意味着将文件拆分为 nParMax 空行数。

但是,有时我会将最后一段在中间拆分(2-3-5 行,而不是完整的 10-15 行)。

我非常感谢您就为什么会发生这种情况(错误的正则表达式模式?)以及如何避免这种情况发生的建议。

提前致谢!

编辑

行为不端的段落:

# sent_id = 170247_3
# text = В то же время видеокадры с места событий свидетельствуют о том, что после звука, похожего на выстрел, находившихся на площади людей охватила паника.
1       В       _       ADP     _       _       4       case    _       O
2       то      _       DET     _       Animacy=Inan|Case=Acc|Gender=Neut|Number=Sing   4       det     _       O
3       же      _       PART    _       _       2       advmod  _       O
4       время   _       NOUN    _       Animacy=Inan|Case=Acc|Gender=Neut|Number=Sing   9       obl     _       O
5       видеокадры      _       NOUN    _       Animacy=Inan|Case=Nom|Gender=Masc|Number=Plur   9       nsubj   _       O
6       с       _       ADP     _       _       7       case    _       O
7       места   _       NOUN    _       Animacy=Inan|Case=Gen|Gender=Neut|Number=Sing   5       nmod    _       O
8       событий _       NOUN    _       Animacy=Inan|Case=Gen|Gender=Neut|Number=Plur   7       nmod    _       O
9       свидетельствуют _       VERB    _       Aspect=Imp|Mood=Ind|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin|Voice=Act      0       root    _       O
10      о       _       ADP     _       _       11      case    _       O
11      том     _       PRON    _       Animacy=Inan|Case=Loc|Gender=Neut|Number=Sing   9       obl     _       O
12      ,       _       PUNCT   _       _       25      punct   _       O
13      что     _       SCONJ   _       _       25      mark    _       O
14      после   _       ADP     _       _       15      case    _       O
15      звука   _       NOUN    _       Animacy=Inan|Case=Gen|Gender=Masc|Number=Sing   25      obl     _       O
16      ,       _       PUNCT   _       _       17      punct   _       O
17      похожего        _       ADJ     _       Case=Gen|Degree=Pos|Gender=Masc|Number=Sing     15      amod    _       O
18      на      _       ADP     _       _       19      case    _       O
19      выстрел _       NOUN    _       Animacy=Inan|Case=Acc|Gender=Masc|Number=Sing   17      obl     _       O
20      ,       _       PUNCT   _       _       15      punct   _       O
21      находившихся    _       VERB    _       Animacy=Anim|Aspect=Imp|Case=Acc|Number=Plur|Tense=Past|VerbForm=Part|Voice=Act 24      acl     _       O
22      на      _       ADP     _       _       23      case    _       O
23      площади _       NOUN    _       Animacy=Inan|Case=Loc|Gender=Fem|Number=Sing    21      obl     _       O
24      людей   _       NOUN    _       Animacy=Anim|Case=Acc|Gender=Masc|Number=Plur   25      obj     _       O
25      охватила        _       VERB    _       Aspect=Perf|Gender=Fem|Mood=Ind|Number=Sing|Tense=Past|VerbForm=Fin|Voice=Act   11      acl     _       O
26      паника  _       NOUN    _       Animacy=Inan|Case=Nom|Gender=Fem|Number=Sing    25      nsubj   _       O
27      .       _       PUNCT   _       _       9       punct   _       O

由此产生的分裂:

# sent_id = 170247_3
# text = В то же время видеокадры с места событий свидетельствуют о том, что после звука, похожего на выстрел, находившихся на площади людей охватила паника.
1       В       _       ADP     _       _       4       case    _       O
2       то      _       DET     _       Animacy=Inan|Case=Acc|Gender=Neut|Number=Sing   4       det     _       O
3

下一个拆分的文件按照它应该的那样干净地开始。有一半的段落丢失了。

编辑 2

VIM 中的相同段落 (# sent_id = 170247_3$) 带有特殊字符 (:set list)。拆分发生在第 3 行(见上文):

# sent_id = 170247_3$
# text = В то же время видеокадры с места событий свидетельствуют о том, что после звука, похожего на выстрел, находившихся на площади людей охватила паника.$
1^IВ^I_^IADP^I_^I_^I4^Icase^I_^IO$
2^Iто^I_^IDET^I_^IAnimacy=Inan|Case=Acc|Gender=Neut|Number=Sing^I4^Idet^I_^IO$
3^Iже^I_^IPART^I_^I_^I2^Iadvmod^I_^IO$
4^Iвремя^I_^INOUN^I_^IAnimacy=Inan|Case=Acc|Gender=Neut|Number=Sing^I9^Iobl^I_^IO$
5^Iвидеокадры^I_^INOUN^I_^IAnimacy=Inan|Case=Nom|Gender=Masc|Number=Plur^I9^Insubj^I_^IO$
6^Iс^I_^IADP^I_^I_^I7^Icase^I_^IO$
7^Iместа^I_^INOUN^I_^IAnimacy=Inan|Case=Gen|Gender=Neut|Number=Sing^I5^Inmod^I_^IO$
8^Iсобытий^I_^INOUN^I_^IAnimacy=Inan|Case=Gen|Gender=Neut|Number=Plur^I7^Inmod^I_^IO$
9^Iсвидетельствуют^I_^IVERB^I_^IAspect=Imp|Mood=Ind|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin|Voice=Act^I0^Iroot^I_^IO$
10^Iо^I_^IADP^I_^I_^I11^Icase^I_^IO$
11^Iтом^I_^IPRON^I_^IAnimacy=Inan|Case=Loc|Gender=Neut|Number=Sing^I9^Iobl^I_^IO$
12^I,^I_^IPUNCT^I_^I_^I25^Ipunct^I_^IO$
13^Iчто^I_^ISCONJ^I_^I_^I25^Imark^I_^IO$
14^Iпосле^I_^IADP^I_^I_^I15^Icase^I_^IO$
15^Iзвука^I_^INOUN^I_^IAnimacy=Inan|Case=Gen|Gender=Masc|Number=Sing^I25^Iobl^I_^IO$
16^I,^I_^IPUNCT^I_^I_^I17^Ipunct^I_^IO$
17^Iпохожего^I_^IADJ^I_^ICase=Gen|Degree=Pos|Gender=Masc|Number=Sing^I15^Iamod^I_^IO$
18^Iна^I_^IADP^I_^I_^I19^Icase^I_^IO$
19^Iвыстрел^I_^INOUN^I_^IAnimacy=Inan|Case=Acc|Gender=Masc|Number=Sing^I17^Iobl^I_^IO$
20^I,^I_^IPUNCT^I_^I_^I15^Ipunct^I_^IO$
21^Iнаходившихся^I_^IVERB^I_^IAnimacy=Anim|Aspect=Imp|Case=Acc|Number=Plur|Tense=Past|VerbForm=Part|Voice=Act^I24^Iacl^I_^IO$
22^Iна^I_^IADP^I_^I_^I23^Icase^I_^IO$

【问题讨论】:

  • 能否请您发布导致您的问题出现问题的那段示例,然后让我们知道(顺便说一句,不是我的反对票)。
  • @RavinderSingh13 根据您的要求编辑
  • 由于有一些反对票,如果反对票的人分享他们这样做的原因,我将非常感激。也许我错过了一些微不足道的东西?
  • 我无法在有两个 pars 的文件上重现它(你给的那个粘贴了两次,中间有一个空行)。由于您使用的是非拉丁字母,因此编码可能是一个问题?无论如何,该模式与我在this answer 中使用的模式非常相似:您将始终打印该行,除非/^$/,在这种情况下您甚至可能不打印。我会看一下该语句并对其进行调试。
  • @EdMorton 谢谢,有道理

标签: regex linux bash awk split


【解决方案1】:

我不确定这是否是您要执行的操作,而是将 X 段的文件拆分为 n 个(下面的10)文件,其中 X 是大于或等于 n 的某个数字,因为我认为你想要做的是:

awk -v RS= -v ORS='\n\n' -n 10 '
    NR==FNR { totParas=NR; parasPerFile=2; next }
    (FNR % parasPerFile) == 1 {
        close(out)
        out = FILENAME "_out" (++c)
        parasLeft = totParas - (FNR - 1)
        parasPerFile = int(parasLeft/n) + (parasLeft%n ? 1 : 0)
    }
    { print > out }
' file file

【讨论】:

  • 非常感谢您的宝贵时间!关于您上面的评论 # of paras == # of empty lines,所以计算哪一个并不重要。我会尝试分割文件,直到我按照你的建议将罪魁祸首归零。
  • 您能否看一下问题中的编辑 2,打开了特殊字符?作为一个疯狂的猜测,当我通过 SSH 在服务器上执行脚本时,可能是由于文件写入过早关闭吗?
  • 我没有在问题中看到任何Edit 2,并且知道您所说的“特殊字符”是什么意思。我想一切皆有可能,但通常像这样的问题只是普通的老错误。
  • 对不起,可能不好。现已添加。
  • Edit 2 下的文字是否表明如果我在您的问题中运行该脚本,是否说明您遇到的问题?如果没有,它对调试您的问题没有用。其中的那些“特殊字符”(^I)只是标签——它们没什么有趣的。您是否尝试过what I suggested yesterday 来隔离问题段落?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
  • 2013-08-11
  • 2019-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多