在终端中根据括号或圆括号(仅限顶级)分割文本文件

2024-03-19

我有几个文本文件 (utf-8),我想在 shell 脚本中处理它们。它们的格式并不完全相同,但如果我只能将它们分解成可食用的块,我就可以处理它。 这可以用 C 或 python 编程,但我不喜欢。

编辑:我用 C 编写了一个解决方案;看我自己的答案。我认为这可能是最简单的方法。如果您认为我错了,请根据我下面的答案中更复杂的示例输入来测试您的解决方案。

——jcxz100

为了清楚起见(并且能够更轻松地调试),我希望将块保存为子文件夹中的单独文本文件。

所有类型的输入文件都包含:

  1. 垃圾线路
  2. 包含垃圾文本的行,后跟开始方括号或圆括号 - 即 '[' '{' '
  3. 有效载荷线
  4. 带有嵌套在顶级对中的方括号或圆括号的行;也被视为有效负载
  5. 带有结束括号或括号的有效负载行 - 即 ']' '}' '>' 或 ')' - 后面可能跟着一些东西(垃圾文本和/或新有效负载的开始)

我想仅根据匹配对来分解输入顶层方括号/圆括号。 这些对内的有效负载不得更改(包括换行符和空格)。 顶级对之外的所有内容都应作为垃圾丢弃。

必须考虑双引号内的任何垃圾或有效负载atomic(作为原始文本处理,因此内部的任何括号或圆括号也应被视为文本)。

下面是一个示例(仅使用 {} 对):

junk text
"atomic junk"

some junk text followed by a start bracket { here is the actual payload
   more payload
   "atomic payload"
   nested start bracket { - all of this line is untouchable payload too
      here is more payload
      "yet more atomic payload; this one's got a smiley ;-)"
   end of nested bracket pair } - all of this line is untouchable payload too
   this is payload too
} trailing junk
intermittent junk
{
   payload that goes in second output file    }
end junk

...抱歉:有些输入文件确实如此混乱。

第一个输出文件应该是:

{ here is the actual payload
   more payload
   "atomic payload"
   nested start bracket { - all of this line is untouchable payload too
      here is more payload
      "yet more atomic payload; this one's got a smiley ;-)"
   end of nested bracket pair } - all of this line is untouchable payload too
   this is payload too
}

...和第二个输出文件:

{
   payload that goes in second output file    }

Note:

  • 我还没有完全决定是否有必要keep输出中的一对开始/结束字符,或者它们本身是否应作为垃圾丢弃。 我认为保留它们的解决方案是更通用的。

  • 同一输入文件中可以混合使用多种类型的顶级括号/圆括号对。

  • 注意:输入文件中有 * 和 $ 字符,因此请避免混淆 bash ;-)

  • 我更喜欢可读性而不是简洁性;但速度不会呈指数级下降。

必备品:

  • 文本内有反斜杠转义的双引号;最好应该处理它们 (我有一个 hack,但它并不漂亮)。

  • 该脚本不应该突破垃圾和/或有效负载中不匹配的方括号/圆括号对(注意:在原子内部,它们must被)允许!)

更远的好东西:

  • 我还没有看到它,但可以推测某些输入可能用单引号而不是双引号来表示原子内容......或者甚至是两者的混合。

  • 如果可以轻松修改脚本以解析类似结构但具有不同开始/结束字符或字符串的输入,那就太好了。

我可以看到这很拗口,但我认为如果我将其分解为更简单的问题,它不会给出一个可靠的解决方案。

主要问题是正确分割输入 - 其他所有内容都可以被忽略或通过黑客“解决”,所以 随意忽略锦上添花更遥远的美好事物.


Given:

$ cat file
junk text
"atomic junk"

some junk text followed by a start bracket { here is the actual payload
   more payload
   "atomic payload"
   nested start bracket { - all of this line is untouchable payload too
      here is more payload
      "yet more atomic payload; this one's got a smiley ;-)"
   end of nested bracket pair } - all of this line is untouchable payload too
   this is payload too
} trailing junk
intermittent junk
{
   payload that goes in second output file    }
end junk

这个 perl 文件会将您描述的块提取到文件中block_1, block_2, etc:

#!/usr/bin/perl
use v5.10;
use warnings;
use strict;

use Text::Balanced qw(extract_multiple extract_bracketed);

my $txt;

while (<>){$txt.=$_;}  # slurp the file

my @blocks = extract_multiple(
    $txt,
    [
        # Extract {...}
        sub { extract_bracketed($_[0], '{}') },
    ],
    # Return all the fields
    undef,
    # Throw out anything which does not match
    1
);
chdir "/tmp";
my $base="block_";
my $cnt=1;
for my $block (@blocks){ my $fn="$base$cnt";
                         say "writing $fn";
                         open (my $fh, '>', $fn) or die "Could not open file '$fn' $!";
                         print $fh "$block\n";
                         close $fh;
                         $cnt++;}

现在的文件:

$ cat block_1
{ here is the actual payload
   more payload
   "atomic payload"
   nested start bracket { - all of this line is untouchable payload too
      here is more payload
      "yet more atomic payload; this one's got a smiley ;-)"
   end of nested bracket pair } - all of this line is untouchable payload too
   this is payload too
}

$ cat block_2
{
   payload that goes in second output file    }

Using Text::Balanced是强大的并且可能是最好的解决方案。

You can用一个 Perl 做这些块regex https://regex101.com/r/3DtI1N/1:

$ perl -0777 -nlE 'while (/(\{(?:(?1)|[^{}]*+)++\})|[^{}\s]++/g) {if ($1) {$cnt++; say "block $cnt:== start:\n$1\n== end";}}' file
block 1:== start:
{ here is the actual payload
   more payload
   "atomic payload"
   nested start bracket { - all of this line is untouchable payload too
      here is more payload
      "yet more atomic payload; this one's got a smiley ;-)"
   end of nested bracket pair } - all of this line is untouchable payload too
   this is payload too
}
== end
block 2:== start:
{
   payload that goes in second output file    }
== end

但这比使用像这样的适当的解析器要脆弱一些Text::Balanced...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在终端中根据括号或圆括号(仅限顶级)分割文本文件 的相关文章

随机推荐