Is there a way to filter a text file using grep (or any other tool) so that you can get a section of the file that is cuffed or braced?
I ended up with several files that look something like this:
universe = {
["stars"] = {
["Sun"] = {
["planets"] = "9",
["life"] = "Yes",
["asteroid"] = "9001"
},
["Alpha Centauri"] = {
["planets"] = "3",
["life"] = "No",
["asteroid"] = "20"
},
["Rigel"] = {
["planets"] = "5",
["life"] = "No",
["asteroid"] = "11"
}
}
}
My intention is to find, for example, every block where ["life"] equals "No". I understand this could be handled better if it was in the database (or something with a structure), but I'm not sure how to convert this data to this.
I have a bunch of files in this format and I would like to run a command that could display the sections (up to the immediate parent bracket) where the condition is true, so for the previous example I would like to get:
["Alpha Centauri"] = {
["planets"] = "3",
["life"] = "No",
["asteroid"] = "20"
},
["Rigel"] = {
["planets"] = "5",
["life"] = "No",
["asteroid"] = "11"
}
Can this be done with GREP? Or is there another tool that could do something like this?
Any help is appreciated. Thanks in advance.
EDIT
Example 2: https://regex101.com/r/jO9dU5/1
source to share
Yes, it is possible via grep which supports the -P
(Perl Regex) option .
$ grep -oPz '.*\[[^\[\]]*\]\s*=\s*\{[^{}]*\["life"\]\s*=\s*"No"[^{}]*}.*' file
["Alpha Centauri"] = {
["planets"] = "3",
["life"] = "No",
["asteroid"] = "20"
},
["Rigel"] = {
["planets"] = "5",
["life"] = "No",
["asteroid"] = "11"
}
From 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
Update:
\[[^\n]*\]\h*=\h*\{(?!,\s*\[[^\[\]]*\]\h*=\h*{).*?\["fontSize"\]\h*=\h*20,.*?\}(?=,\s*\[[^\[\]]*\]\h*=\h*{|\s*})
$ 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)
The DOTALL modifier, which makes dots in your regex equal line breaks.
source to share
Try this Lua program:
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")
Add a definition universe
before this code.
If you really want to process the text, try this instead:
S=[[
universe = {
...
}
]]
for w in S:gmatch('%b[] = {[^{]-"No".-},?') do
print(w)
end
source to share
Using the correct lua parser in perl
This is not a quick dirty snippet, but a reliable way to query lua DS:
use strict; use warnings;
use Data::Lua; # lua 2 perl parser
use Data::Dumper; # to dump Data Structures (in color)
# retrieving the lua'DS in a perl DS
my $root = Data::Lua->parse_file('lua.conf');
# iterating over keys of planet HASH
foreach my $planet (keys $root->{universe}->{stars}) {
print Dumper { $planet => $root->{universe}->{stars}->{$planet} }
if $root->{universe}->{stars}->{$planet}->{life} eq "No";
}
Output
$VAR1 = {
'Rigel' => {
'planets' => '5',
'life' => 'No',
'asteroid' => '11'
}
};
$VAR1 = {
'Alpha Centauri' => {
'asteroid' => '20',
'life' => 'No',
'planets' => '3'
}
};
how
- install
Data::Lua
if not already installed with# cpan Data::Lua
- put the data structure in a file
lua.conf
- put this script in the same directory in the example
lua_DS_parser.pl
- run your script with
$ perl lua_DS_parser.pl
- enjoy;)
source to share