【问题标题】:Bash: Split text file ahead of regex matchBash:在正则表达式匹配之前拆分文本文件
【发布时间】:2014-01-22 16:19:02
【问题描述】:

我想在 55 个“显示”行之后拆分一个文本文件(1000-2000 行)。要计算实际显示的行数,

grep -n "^L 7p 39 C\|^N 2" airportdata.txt | cut -f1 -d: >> matches_all.txt

按需要工作。

现在我有了显示行的总数,包括“显示内容”所在的行号。

我的问题:我只允许拆分N 2 前面的文件(请参阅示例内容)以保留文件结构。我不确定如何实现这一目标。我的尝试是查看匹配号 56 是否为N 2。那么拆分就简单了:

head -55 airportdata.txt > apd_1.txt
tail -n +55 airportdata.txt > apd_2.txt 

在保持文件结构完整的同时做到这一点。

如果我匹配其他行之一,我必须在文件中“向上走”并找到行数较少的行,其中包含 N 2 并在那里拆分文件。而这正是我迄今为止没有成功的部分。

非常欢迎任何想法。

一切顺利,

克里斯


文件结构: N n 定义列数。以下行将分布到这些列中,直到新的N n 发生更改。

N 2 表示两列,因此接下来的两行构成一个“显示行”。

N 9 表示九列,后面的每九行组成一个“显示行”。

示例内容,来自airportdata.txt

N 2
L 7p 40 L @:6.5p:CYLW@::
L 7p 39 R 1410ft / nil
N 9
L 7p 39 L 1
L 7p 39 L 16
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 2500*x61
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 34
L 7p 39 R -
N 2
L 7p 40 L @:6.5p:CYMJ@::
L 7p 39 R 1890ft / nil
N 9
L 7p 39 L 1
L 7p 39 L 11L
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 2500 x46
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 29R
L 7p 39 R 1
L 7p 39 L G
L 7p 39 L 11R
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 2200 x46
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 29L
L 7p 39 R G
N 2
L 7p 40 L @:6.5p:CYVR@::
L 7p 39 R 10ft / n.a
N 9
L 7p 39 L 3
L 7p 39 L 08L
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 3000 x61
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 26R
L 7p 39 R 3
L 7p 39 L 3
L 7p 39 L 08R
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 3500*x61
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 26L
L 7p 39 R 1
L 7p 39 L 1
L 7p 39 L 12
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 2200 x61
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 30
L 7p 39 R G
N 2
L 7p 40 L @:6.5p:CYWG@::
L 7p 39 R 780ft / 8
N 9
L 7p 39 L 2
L 7p 39 L 36
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 3300 x61
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 18
L 7p 39 R V
L 7p 39 L 1
L 7p 39 L 13
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 2600 x61
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 31
L 7p 39 R 1

适应示例内容可能的结果是:

条件:显示4行后拆分

apd_1.txt:

N 2
L 7p 40 L @:6.5p:CYLW@::
L 7p 39 R 1410ft / nil
N 9
L 7p 39 L 1
L 7p 39 L 16
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 2500*x61
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 34
L 7p 39 R -

apd_2.txt:

N 2
L 7p 40 L @:6.5p:CYMJ@::
L 7p 39 R 1890ft / nil
N 9
L 7p 39 L 1
L 7p 39 L 11L
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 2500 x46
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 29R
L 7p 39 R 1
L 7p 39 L G
L 7p 39 L 11R
L 7p 39 L \040
L 7p 39 L \040
L 7p 39 C 2200 x46
L 7p 39 R \040
L 7p 39 R \040
L 7p 39 R 29L
L 7p 39 R G
[and all the rest]

第五个匹配的行不是N 2,因此必须在前一个N 2前面进行剪切

【问题讨论】:

  • 愿意提供帮助,但我认为我并不完全理解这个问题。就像一个提示:Csplit 在这里可能会有所帮助:man7.org/linux/man-pages/man1/csplit.1.html
  • 如果您将问题改写为 5 行而不是 56 行,那么人们将很容易看到您所要求的结果。祝你好运。
  • 你固定在 bash 上吗?在 perl 或 ruby​​ 中可能更容易,您可以更轻松地进行一些展望。
  • 我认为您需要更清楚地了解“显示行”是什么:它是文件中由...分隔或包含...的多行文本?? ?

标签: regex bash sed awk


【解决方案1】:

不确定我是否了解您的所有条件,但我认为最简单的方法是使用循环,例如

#!/bin/bash
apd=0
while read line; do
  [[ $line == "N 2"* ]] && apd=$(($apd+1))
  echo "$line" >> "add_${apd}.txt"
done < "airportdata.txt"     

在您的示例中,aiportdata.txt 将输出 4 个文件 add_1.txt add_2.txt add_3.txt add_4.txt,每个文件都以 N 2 开头

【讨论】:

  • 每次提到N 2 时都会很好地拆分文件。期望的结果是N 2 前面的拆分,matches_all.txt 文件中的行号 =
  • @Chris 所以基本上应该每 56 行拆分一次或者遇到N 2?
  • 不是真的——我尽力用另一种方式解释它:文件airportdata.txt 用于填充最大容量为55 行的框。并非文件中的每一行都被打印,因为这些行被解析为几列,并且文件只能在N 2 处拆分。这可能导致“可见”行数少于 55(框中少于 55 行)。问题中的 grep 是一个近似值:它匹配 9 列行的中间列和新机场集的开始。但结果足够接近,可以用作指导。
【解决方案2】:

如果我理解正确,那么您正在寻找这样的东西:

awk -v n=55 -v f1=apd_1.txt -v f2=apd_2.txt '
    /^N/ {++c}
    c <= n { print > f1 }
    c > n { print > f2 }
' < airportdata.txt

即:

  • 将一些变量传递给awkn = 要拆分的“阈值”数,f1f2 两个输出文件
  • 如果一行以N 开头,则增加计数
  • 如果计数小于或等于阈值,则打印到第一个文件
  • 如果计数大于阈值,则打印到第二个文件

【讨论】:

  • 感谢您的解释。不幸的是,这不是我正在寻找的分裂。仅仅寻找N n 的出现并不能减少它。 n=55matches_all.txt 中的所有结果行都有效。但只有在下一行是N 2 时才能进行剪切。所以它变得更像一个 n=
  • @Chris 在我看来,您可以通过调整n=55 设置(更改为n=56? 或n=54?)或调整c &lt;= n 来实现您想要的, c &gt; n 里面的条件。没有?
  • 享受无限循环 getline 将在您最不期待的某一天提供:-)。阅读 awk.info/?tip/getline 并确保在使用 getline 之前完全理解所有注意事项。
猜你喜欢
  • 2017-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 2011-04-11
  • 2019-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多