I'd like to do grouping of regular expressions with eiffel. How do I do something like
l_reg.compile ("^([0-9]{3}) (rabbit[0-9]).*")
l_groups := l_reg.groups ("123 rabbit1")
my_first_rabbit := l_groups.at (2)
Didn't find any example on groups, LX_DFA_REGULAR_EXPRESSION class and other googlings
One solution is to use RX_PCRE_REGULAR_EXPRESSION instead of LX_DFA_REGULAR_EXPRESSION:
Including $ISE_LIBRARY\contrib\library\gobo\library\regexp\src\library.ecf library
l_reg: RX_PCRE_REGULAR_EXPRESSION
...
l_reg.compile ("^([0-9]{3}) (rabbit[0-9]).*")
l_reg.match ("123 rabbit1")
my_first_rabbit := l_reg.captured_substring (2)
There is no groups routine, although it could be implemented by calling captured_substring internally. There is only a routine split which does the reverse: returns the substrings which did not match the regular expression.
Something like
regex_groups (a_haystack, a_needle: STRING): ARRAY[STRING]
-- Test with https://www.regextester.com/1911
require
regex_match (a_haystack, a_needle)
local
l_reg: RX_PCRE_REGULAR_EXPRESSION
l_index: like {RX_PCRE_REGULAR_EXPRESSION}.match_count
do
create Result.make_empty
create l_reg.make
l_reg.compile (a_needle)
if l_reg.is_compiled then
l_reg.match (a_haystack)
from
l_index := 1
until
l_index > l_reg.match_count
loop
Result.extend (l_reg.captured_substring (l_index))
l_index := l_index + 1
end
else
--- error compiling regex
fallible.set_last_error (create {SIT_INTERNAL_ERROR}.make ("regex_group-> regex does not compile:" + a_needle))
end
ensure
not fallible.has_error
instance_free: Class
end
you could test your regex here: https://www.regextester.com/1911
Related
os.Stat() returns a FileInfo object, which has a Sys() method that returns an Interface{} with no methods.
Though I am able to fmt.Printf() it to "see" the "Gid", I am unable to access "Gid" programmatically.
How do I retrieve the "Gid" of a file here?
file_info, _ := os.Stat(abspath)
file_sys := file_info.Sys()
fmt.Printf("File Sys() is: %+v", file_sys)
Prints:
File Sys() is: &{Dev:31 Ino:5031364 Nlink:1 Mode:33060 Uid:1616 Gid:31 X__pad0:0 Rdev:0 Size:32 Blksize:32768 Blocks:0 Atim:{Sec:1564005258 Nsec:862700000} Mtim:{Sec:1563993023 Nsec:892256000} Ctim:{Sec:1563993023 Nsec:893251000} X__unused:[0 0 0]}
Note: I do not need a portable solution, it just has to work on Linux (notable because Sys() is known to be flaky).
Possibly related: Convert interface{} to map in Golang
The reflect module showed that the data type for Sys()'s return is *syscall.Stat_t, so this seems to work to get the Gid of a file as a string:
file_info, _ := os.Stat(abspath)
file_sys := file_info.Sys()
file_gid := fmt.Sprint(file_sys.(*syscall.Stat_t).Gid)
Please let me know if there is a better way to do this.
Id like to uncompress a file with bzip2 myFile.bz2 which class do I have to use for that?
I tried to find it into base kernel documentation which made the most sense for me and didn't find it
This works:
make
local
l_env:EXECUTION_ENVIRONMENT
do
create l_env
l_env.system ("bzip2 test.txt")
end
My final solution working on linux with pipes is following:
feature -- Commands
piped_command_result (a_command: STRING): detachable PROCESS_COMMAND_RESULT
-- https://groups.google.com/forum/#!topic/eiffel-users/O9KEtBSPrf4
local
l_cmd: READABLE_STRING_32
l_args: ARRAYED_LIST [READABLE_STRING_32]
l_proc: like {BASE_PROCESS_FACTORY}.process_launcher
l_err, l_res: STRING
l_err_spec, l_res_spec: SPECIAL [NATURAL_8]
do
create l_res.make (0)
create l_err.make (0)
create l_res_spec.make_filled (0, 1024)
create l_err_spec.make_filled (0, 1024)
l_cmd := (create {EXECUTION_ENVIRONMENT}).default_shell
if l_cmd.is_empty then
l_cmd := {STRING_32} "/bin/bash" -- or either "/bin/sh"
end
create l_args.make (2)
l_args.extend ("-c")
l_args.extend (a_command)
l_proc := (create {BASE_PROCESS_FACTORY}).process_launcher (l_cmd, l_args, Void)
l_proc.set_hidden (True)
l_proc.set_separate_console (False)
l_proc.redirect_output_to_stream
l_proc.redirect_error_to_stream
l_proc.launch
check
process_launched: l_proc.launched
then
-- read output
from
until
l_proc.has_output_stream_closed or l_proc.has_output_stream_error
loop
l_proc.read_output_to_special (l_res_spec)
append_special_of_natural_8_to_string_8 (l_res_spec, l_res)
end
-- read error
from
until
l_proc.has_error_stream_closed or l_proc.has_error_stream_error
loop
l_proc.read_error_to_special (l_err_spec)
append_special_of_natural_8_to_string_8 (l_err_spec, l_err)
end
l_proc.wait_for_exit
create Result.make (l_proc.exit_code, l_res, l_err)
end
ensure
instance_free: Class
end
feature {NONE} -- Implementation
append_special_of_natural_8_to_string_8 (spec: SPECIAL [NATURAL_8]; a_output: STRING)
local
i,n: INTEGER
do
from
i := spec.lower
n := spec.upper
until
i > n
loop
a_output.append_code (spec[i])
i := i + 1
end
ensure
instance_free: Class
end
Credits to google groups eiffel users
Note that with another user like an app launched by apache, you have to check your environment variables and $PATH so that it can work!
I have an unknown identifier on the local like some_values.cursor, I really don't understand why!
qry_update_set_fields (some_keys, some_values, some_unstored_field_names: LINKED_LIST[STRING]): STRING
require
same_some_keys_some_values_count: some_keys.count = some_values.count
local
l_val_c: like some_values.new_cursor
do
Result := ""
l_val_c := some_values.new_cursor
across
some_keys as l_key_c
loop
Result := l_key_c.item + "=" + l_val_c.item + ","
l_val_c.forth
end
if Result.ends_with (",") then
Result.remove_tail (1)
end
ensure
dont_modify_parameters: old some_keys.is_equal (some_keys) and old some_values.is_equal (some_values)
end
working
l_val_c: LINKED_LIST_CURSOR [STRING]
Neither working
l_val_c: LINKED_LIST_CURSOR [like some_values.item]
The example tries using an argument in the qualified anchored type like argument.some_feature. This is not supported. Types, anchored to arguments, are not part of the standard Eiffel and are supported only for backward compatibility in the form like argument.
I am writing my first custom matcher in rspec. I would like to provide a failure message with a break down on why the comparison has failed. Effectively I would like to output the differences between the expected and the actual object. I effectively just need to do this with 2 arrays on the object. I have done some research and am trying to use =~ as described here. It mentions it has an informative failure message but I am struggling to access the failure message. I would effectively just like to return the combined failure message for two separate arrays to give an informative reason for the matcher returning false.
My attempt is as follows
RSpec::Matchers.define :have_same_state_as_measure_table do |expected_measure_table , max_delta = 1e-06|
match do |actual_measure_table|
actual_measure_table.equivalence(expected_measure_table, max_delta)
end
description do
"checks if measure has same state as expected measure table within a given number of precision"
end
# Optional method description
description do
"checks if measure has same state as expected measure table, within a given level of precision"
end
# Optional failure messages
failure_message do |actual_measure_table|
mismatch_string = ""
mismatch_string += (actual_measure_table.columns =~ expected_measure_table.columns || "")
mismatch_string += (actual_measure_table.names =~ expected_measure_table.names || "")
"Measure tables missmatch as follows %s" % (mismatch_string.to_s)
end
failure_message_when_negated do |actual_measure_table|
"expected friend not to be in zipcode"
end
end
My final matcher was as follows :
class CompareMeasureTables
attr_reader :expected_measure_table, :max_delta, :actual_measure_table
def initialize(expected_measure_table, max_delta=1e-06)
#expected_measure_table = expected_measure_table
#max_delta = max_delta
end
def description
"Checks if measure has same state as expected measure table, within a given level of precision"
end
def matches?(actual_measure_table)
#actual_measure_table = actual_measure_table
actual_measure_table.equivalence(expected_measure_table, max_delta, false)
end
def failure_message
#mismatch_description = ""
if actual_measure_table.columns.sort != expected_measure_table.columns.sort
#mismatch_description += "\nColumns mismatch \nExpected =" + expected_measure_table.columns.inspect
#mismatch_description += "\nActual =" + actual_measure_table.columns.inspect
end
if (#mismatch_description == "")
#mismatch_description += "\nData mismatch \nExpected =" + (expected_measure_table.records - actual_measure_table.records).inspect
#mismatch_description += "\nActual =" + (actual_measure_table.records - expected_measure_table.records).inspect
#mismatch_description += "\nTolerance set at #{#max_delta}"
end
"Measure tables mismatch as follows %s" % (#mismatch_description)
end
end
Simple
How can I get a list of the files that are inside directory using eiffel?
For example:
class CARPETAS
creation
make
feature {NONE}
make is
local
directory: DIRECTORY
path: STRING
do
path := "." -- Current directory
!!directory.scan_with(path)
list_directory(directory)
end
list_directory(directory: DIRECTORY) is
local
i: INTEGER
do
std_output.put_string("Content of " + directory.path + "%N")
from
i := directory.lower
until
i > directory.upper
loop
std_output.put_string("%T" + directory.name(i) + "%N")
i := i + 1
end
end
end
with recent version of Eiffel, I would recommend to use DIRECTORY.entries
local
p: PATH
do
across dir.entries as ic loop
p := ic.item.path
-- then use interface of PATH, such as PATH.name
end
end
note that the base_extension library also provides DIRECTORY_VISITOR , which is helpful to iterate recursively on directories