Bash:在正则表达式匹配之前拆分文本文件

时间:2014-01-21 21:20:47

标签: regex bash sed awk

我想在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

之前进行剪切

2 个答案:

答案 0 :(得分:0)

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

#!/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

开头

答案 1 :(得分:0)

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

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开头,则递增计数
  • 如果计数小于或等于阈值,则打印到第一个文件
  • 如果计数大于阈值,则打印到第二个文件