有没有一种方法可以使用grep(或任何其他工具)过滤文本文件,以便您可以获取包含在花括号或方括号中的文件部分?

我有几个文件看起来像这样:

universe = {
    ["stars"] = {
        ["Sun"] = {
            ["planets"] = "9",
            ["life"] = "Yes",
            ["asteroid"] = "9001"
        },
        ["Alpha Centauri"] = {
            ["planets"] = "3",
            ["life"] = "No",
            ["asteroid"] = "20"
        },
        ["Rigel"] = {
            ["planets"] = "5",
            ["life"] = "No",
            ["asteroid"] = "11"
        }
    }
}

我的意图是找到每个 ["life"] 等于 "No" 的块。我意识到如果它在数据库(或具有结构的东西)中,可能处理得更好,但我不知道如何把这个数据转换到这个结构中。

我有一堆这种格式的文件,我想运行一个命令,可以显示符合条件的部分(直到最近的父括号),所以对于上一个例子,我想获得:

        ["Alpha Centauri"] = {
            ["planets"] = "3",
            ["life"] = "No",
            ["asteroid"] = "20"
        },
        ["Rigel"] = {
            ["planets"] = "5",
            ["life"] = "No",
            ["asteroid"] = "11"
        }

这可以用 GREP 做到吗?还是有任何其他工具可以做类似的事情?

非常感谢任何帮助。预先感谢。

编辑

示例 2:https://regex101.com/r/jO9dU5/1

点赞
用户3297613
用户3297613

是的,可以使用支持“-P”(_Perl Regex_)参数的grep实现。

$ grep -oPz '.*\[[^\[\]]*\]\s*=\s*\{[^{}]*\["life"\]\s*=\s*"No"[^{}]*}.*' file
        ["Alpha Centauri"] = {
            ["planets"] = "3",
            ["life"] = "No",
            ["asteroid"] = "20"
        },
        ["Rigel"] = {
            ["planets"] = "5",
            ["life"] = "No",
            ["asteroid"] = "11"
        }

DEMO

grep --help

 -z, --null-data           a data line ends in 0 byte, not newline
 -o, --only-matching       show only the part of a line matching PATTERN

更新:

\[[^\n]*\]\h*=\h*\{(?!,\s*\[[^\[\]]*\]\h*=\h*{).*?\["fontSize"\]\h*=\h*20,.*?\}(?=,\s*\[[^\[\]]*\]\h*=\h*{|\s*})

DEMO

$ pcregrep -oM '(?s)[^\n]*\[[^\n]*\]\h*=\h*\{(?!,\s*\[[^\[\]]*\]\h*=\h*{).*?\["fontSize"\]\h*=\h*20,.*?\}(?=,\s*\[[^\[\]]*\]\h*=\h*{|\s*})' file
    ["frame 1"] = {
        ["fontSize"] = 20,
        ["displayStacks"] = "%p",
        ["xOffset"] = 251.000518798828,
        ["stacksPoint"] = "BOTTOM",
        ["regionType"] = "icon",
        ["yOffset"] = 416.000183105469,
        ["anchorPoint"] = "CENTER",
        ["parent"] = "Target Shit",
        ["numTriggers"] = 1,
        ["customTextUpdate"] = "update",
        ["id"] = "Invulnerabilities 2",
        ["icon"] = true,
        ["fontFlags"] = "OUTLINE",
        ["stacksContainment"] = "OUTSIDE",
        ["zoom"] = 0,
        ["auto"] = true,
        ["selfPoint"] = "CENTER",
        ["width"] = 60,
        ["frameStrata"] = 1,
        ["desaturate"] = false,
        ["stickyDuration"] = true,
        ["font"] = "Emblem",
        ["inverse"] = false,
        ["height"] = 60,
    }
    ["frame 2"] = {
        ["fontSize"] = 20,
        ["displayStacks"] = "%p",
        ["parent"] = "Target Shit",
        ["xOffset"] = 118.000427246094,
        ["stacksPoint"] = "BOTTOM",
        ["anchorPoint"] = "CENTER",
        ["untrigger"] = {
        },
        ["regionType"] = "icon",
        ["color"] = {
            1, -- [1]
            1, -- [2]
            1, -- [3]
            1, -- [4]
        },
        ["desaturate"] = false,
        ["frameStrata"] = 1,
        ["stickyDuration"] = true,
        ["width"] = 60,
        ["font"] = "Emblem",
        ["inverse"] = false,
        ["icon"] = true,
        ["height"] = 60,
        ["yOffset"] = 241
    }

(?s) DOTALL修饰符,使您的正则表达式中的点甚至匹配换行符。

2014-12-10 16:08:43
用户4240242
用户4240242

你可以使用类似于如下的命令:

grep -C 2 -E 'life.+= "No"' path_to_file

但是在我看来,更好的方法是将文件转换为一些通用的格式。

2014-12-10 16:15:30
用户465183
用户465183

perl中使用适当的lua解析器

这不是一个快速而简单的片段,而是一种查询lua数据结构的强大方式:

use strict; use warnings;
use Data::Lua;                              # lua 2 perl解析器
use Data::Dumper;                           # 用于转储数据结构(带有颜色)

# 从perl数据结构中检索lua数据结构
my $root = Data::Lua->parse_file('lua.conf');

# 循环星球哈希键
foreach my $planet (keys $root->{universe}->{stars}) {
    print Dumper { $planet => $root->{universe}->{stars}->{$planet} }
        if $root->{universe}->{stars}->{$planet}->{life} eq "No";
}

输出

$VAR1 = {
     'Rigel' => {
            'planets' => '5',
            'life' => 'No',
            'asteroid' => '11'
           }
    };
$VAR1 = {
     'Alpha Centauri' => {
                'asteroid' => '20',
                'life' => 'No',
                'planets' => '3'
               }
    };

如何使用

  • 如果未安装,请使用#cpan Data :: Lua安装Data::Lua
  • 将数据结构放入文件“lua.conf”中
  • 将此脚本放入相同的目录中,例如lua_DS_parser.pl
  • 使用$ perl lua_DS_parser.pl运行脚本
  • 尽情享受 ;)
2014-12-10 16:43:09
用户107090
用户107090

尝试这个 Lua 程序:

local function find(w,t,p)
    for k,v in pairs(t) do
        if v==w then
            print(p.."."..k)
        elseif type(v)=="table" then
            find(w,v,p.."."..k)
        end
    end
end

find("No",universe,"universe")

在此代码前添加 universe 的定义。

如果你真的想进行文本处理,可尝试以下代码:

S=[[
universe = {
...
}
]]

for w in S:gmatch('%b[] = {[^{]-"No".-},?') do
    print(w)
end
2014-12-10 18:31:52