1212 COMPARE <actual> AGAINST <expected>
1313 REPLACE <pattern> WITH <replacement> IN <path>
1414 DROP LINES MATCHING <pattern> IN <path>
15- KEEP LINES MATCHING <pattern> IN <path >
15+ EXTRACT STDOUT FROM <observation> INTO <destination >
1616 SORT <path>
1717 COPY <source> TO <destination>
1818 TREE <directory> INTO <destination>
@@ -266,7 +266,7 @@ def command_filter(self, keyword, operands, line_number):
266266 if len (operands ) != 5 or operands [0 ] != "LINES" \
267267 or operands [1 ] != "MATCHING" or operands [3 ] != "IN" :
268268 raise TestFailure (
269- line_number , f "usage: { keyword } LINES MATCHING <regex> IN <file>" )
269+ line_number , "usage: DROP LINES MATCHING <regex> IN <file>" )
270270 pattern , replacement , name = operands [2 ], None , operands [4 ]
271271
272272 path = self .resolve (name , line_number )
@@ -278,10 +278,9 @@ def command_filter(self, keyword, operands, line_number):
278278 content = expression .sub (
279279 self .expand (replacement , line_number ).replace ("\\ " , "\\ \\ " ), content )
280280 else :
281- keep = keyword == "KEEP"
282281 content = "" .join (
283282 line for line in content .splitlines (keepends = True )
284- if bool ( expression .search (line )) == keep )
283+ if not expression .search (line ))
285284 self .write (path , content )
286285
287286 def command_tree (self , operands , line_number ):
@@ -330,6 +329,22 @@ def command_checksum(self, operands, line_number):
330329 with open (self .resolve (operands [1 ], line_number ), "rb" ) as handle :
331330 self .environment [name ] = hashlib .sha256 (handle .read ()).hexdigest ()
332331
332+ def command_extract (self , operands , line_number ):
333+ if len (operands ) != 5 or operands [0 ] != "STDOUT" \
334+ or operands [1 ] != "FROM" or operands [3 ] != "INTO" :
335+ raise TestFailure (
336+ line_number ,
337+ "usage: EXTRACT STDOUT FROM <observation> INTO <destination>" )
338+ content = self .read (self .resolve (operands [2 ], line_number ), line_number )
339+ extracted = []
340+ for line in content .splitlines ():
341+ if line == "1>" :
342+ extracted .append ("" )
343+ elif line .startswith ("1> " ):
344+ extracted .append (line [len ("1> " ):])
345+ self .write (self .resolve (operands [4 ], line_number ),
346+ "" .join (line + "\n " for line in extracted ))
347+
333348 def command_sort (self , operands , line_number ):
334349 if len (operands ) != 1 :
335350 raise TestFailure (line_number , "usage: SORT <file>" )
@@ -482,6 +497,9 @@ def collect(destination, tokens):
482497 elif statement .keyword == "CHECKSUM" and len (operands ) == 4 :
483498 definitions .append ((position , operands [3 ], statement .number ))
484499 collect (consumed , [operands [1 ]])
500+ elif statement .keyword == "EXTRACT" and len (operands ) == 5 :
501+ record (artifacts , operands [4 ], (statement .number , "EXTRACT" ))
502+ collect (consumed , [operands [2 ]])
485503 elif statement .keyword == "STAT" and len (operands ) == 4 :
486504 record (artifacts , operands [3 ], (statement .number , "STAT" ))
487505 collect (consumed , [operands [1 ]])
@@ -557,7 +575,7 @@ def run_script(path, binary, environment):
557575 interpreter .command_compare (rest , number )
558576 elif keyword == "ENV" :
559577 interpreter .command_env (rest , number )
560- elif keyword in ("REPLACE" , "DROP" , "KEEP" ):
578+ elif keyword in ("REPLACE" , "DROP" ):
561579 interpreter .command_filter (keyword , rest , number )
562580 elif keyword == "TREE" :
563581 interpreter .command_tree (rest , number )
@@ -567,6 +585,8 @@ def run_script(path, binary, environment):
567585 interpreter .command_compress (rest , number )
568586 elif keyword == "CHECKSUM" :
569587 interpreter .command_checksum (rest , number )
588+ elif keyword == "EXTRACT" :
589+ interpreter .command_extract (rest , number )
570590 elif keyword == "SORT" :
571591 interpreter .command_sort (rest , number )
572592 elif keyword == "STAT" :
0 commit comments