TemplateApp employs principle of least effort to boost individuals to quickly recognize problem and confidently build solution. Builder features are generated GENERIC solution which is based on human analogy.
For example, assuming
user1 has created a solution to parse the output of "
ls - l" Linux command line such as
Output of "ls -l" Linux command line
----------
lrwxr-xr-x 1 user1 staff 13 Sep 23 11:43 test_script -> ../test_ws.py
-rw-r--r-- 1 user1 staff 748 Jul 5 12:13 test_ws.c
User snippet solution for "ls -l" Linux command line
Let's call this solution as snippet_to_parse_linux_ls_l_output
----------
start() letter(var_ftype, -)mixed_word(var_fperms) digits(var_hard_links) word(var_fowner) letters(var_fgroup) digits(var_fsize) mixed_word(var_date_n_time, 2_group_occurrences) mixed_words(var_file_name) data(->, or_empty) mixed_words(var_real_file, or_empty) end() -> record
Generated TextFSM template
Let's call this solution as textfsm_template_to_parse_linux_ls_l_output
----------
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-23 00:05
################################
Value ftype (([a-zA-Z])|-)
Value fperms ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value hard_links (\d+)
Value fowner ([a-zA-Z][a-zA-Z0-9]*)
Value fgroup ([a-zA-Z]+)
Value fsize (\d+)
Value date_n_time ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( +[\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*){2})
Value file_name ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)*)
Value real_file (((([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)*))|))
Start
^${ftype}${fperms} +${hard_links} +${fowner} +${fgroup} +${fsize} +${date_n_time} +${file_name}\s*(->|)\s*${real_file}$$ -> Record
Test Result is
----------
Total-rows-count: 2
[{'ftype': 'l', 'fperms': 'rwxr-xr-x', 'hard_links': '1', 'fowner': 'user1', 'fgroup': 'staff', 'fsize': '13', 'date_n_time': 'Sep 23 11:43', 'file_name': 'test_script', 'real_file': '../test_ws.py'}, {'ftype': '-', 'fperms': 'rw-r--r--', 'hard_links': '1', 'fowner': 'user1', 'fgroup': 'staff', 'fsize': '748', 'date_n_time': 'Jul 5 12:13', 'file_name': 'test_ws.c', 'real_file': ''}]
or
Total-rows-count: 2
+-------+-----------+------------+--------+--------+-------+--------------+-------------+---------------+
| ftype | fperms | hard_links | fowner | fgroup | fsize | date_n_time | file_name | real_file |
+-------+-----------+------------+--------+--------+-------+--------------+-------------+---------------+
| l | rwxr-xr-x | 1 | user1 | staff | 13 | Sep 23 11:43 | test_script | ../test_ws.py |
| - | rw-r--r-- | 1 | user1 | staff | 748 | Jul 5 12:13 | test_ws.c | |
+-------+-----------+------------+--------+--------+-------+--------------+-------------+---------------+
User1 decides to give the generated TextFSM template (i.e.,
textfsm_template_to_parse_linux_ls_l_output) to development team and other groups to test and provide feedback.
User-k from other group adds comment
textfsm_template_to_parse_linux_ls_l_output template can parse the correct result for
"ls -l" Unix--like command line of Darwin kernel (i.e., Unix Operating System of macOS)
----------
lrwxr-xr-x 1 userk staff 13 Sep 23 11:43 test_script -> ../test_ws.py
-rw-r--r-- 1 userk staff 748 Jul 5 12:13 test_ws.c
Test Result is
----------
Total-rows-count: 2
[{'ftype': 'l', 'fperms': 'rwxr-xr-x', 'hard_links': '1', 'fowner': 'userk', 'fgroup': 'staff', 'fsize': '13', 'date_n_time': 'Sep 23 11:43', 'file_name': 'test_script', 'real_file': '../test_ws.py'}, {'ftype': '-', 'fperms': 'rw-r--r--', 'hard_links': '1', 'fowner': 'userk', 'fgroup': 'staff', 'fsize': '748', 'date_n_time': 'Jul 5 12:13', 'file_name': 'test_ws.c', 'real_file': ''}]
or
Total-rows-count: 2
+-------+-----------+------------+--------+--------+-------+--------------+-------------+---------------+
| ftype | fperms | hard_links | fowner | fgroup | fsize | date_n_time | file_name | real_file |
+-------+-----------+------------+--------+--------+-------+--------------+-------------+---------------+
| l | rwxr-xr-x | 1 | userk | staff | 13 | Sep 23 11:43 | test_script | ../test_ws.py |
| - | rw-r--r-- | 1 | userk | staff | 748 | Jul 5 12:13 | test_ws.c | |
+-------+-----------+------------+--------+--------+-------+--------------+-------------+---------------+
HOWEVER,
textfsm_template_to_parse_linux_ls_l_output template is able to parse the result for
"ls -lT" Unix--like command line of macOS, but with UNEXPECTED DATA in "file_name" column.
----------
lrwxr-xr-x 1 userk staff 13 Sep 23 11:43:44 2023 test_script -> ../test_ws.py
-rw-r--r-- 1 userk staff 748 Jul 5 12:13:13 2023 test_ws.c
Test Result is
----------
Total-rows-count: 2
[{'ftype': 'l', 'fperms': 'rwxr-xr-x', 'hard_links': '1', 'fowner': 'userk', 'fgroup': 'staff', 'fsize': '13', 'date_n_time': 'Sep 23 11:43:44', 'file_name': '2023 test_script', 'real_file': '../test_ws.py'}, {'ftype': '-', 'fperms': 'rw-r--r--', 'hard_links': '1', 'fowner': 'userk', 'fgroup': 'staff', 'fsize': '748', 'date_n_time': 'Jul 5 12:13:13', 'file_name': '2023 test_ws.c', 'real_file': ''}]
or
Total-rows-count: 2
+-------+-----------+------------+--------+--------+-------+-----------------+------------------+---------------+
| ftype | fperms | hard_links | fowner | fgroup | fsize | date_n_time | file_name | real_file |
+-------+-----------+------------+--------+--------+-------+-----------------+------------------+---------------+
| l | rwxr-xr-x | 1 | userk | staff | 13 | Sep 23 11:43:44 | 2023 test_script | ../test_ws.py |
| - | rw-r--r-- | 1 | userk | staff | 748 | Jul 5 12:13:13 | 2023 test_ws.c | |
+-------+-----------+------------+--------+--------+-------+-----------------+------------------+---------------+
Userk asks
user1 to support solution for macOS command line.
First, user1 combining current test data with userk's test data, and then perform testing
----------
lrwxr-xr-x 1 user1 staff 13 Sep 23 11:43 test_script -> ../test_ws.py
-rw-r--r-- 1 user1 staff 748 Jul 5 12:13 test_ws.c
lrwxr-xr-x 1 userk staff 13 Sep 23 11:43 test_script -> ../test_ws.py
-rw-r--r-- 1 userk staff 748 Jul 5 12:13 test_ws.c
lrwxr-xr-x 1 userk staff 13 Sep 23 11:43:44 2023 test_script -> ../test_ws.py
-rw-r--r-- 1 userk staff 748 Jul 5 12:13:13 2023 test_ws.c
Test Result is
----------
Total-rows-count: 6
+-------+-----------+------------+--------+--------+-------+-----------------+------------------+---------------+
| ftype | fperms | hard_links | fowner | fgroup | fsize | date_n_time | file_name | real_file |
+-------+-----------+------------+--------+--------+-------+-----------------+------------------+---------------+
| l | rwxr-xr-x | 1 | user1 | staff | 13 | Sep 23 11:43 | test_script | ../test_ws.py |
| - | rw-r--r-- | 1 | user1 | staff | 748 | Jul 5 12:13 | test_ws.c | |
| l | rwxr-xr-x | 1 | userk | staff | 13 | Sep 23 11:43 | test_script | ../test_ws.py |
| - | rw-r--r-- | 1 | userk | staff | 748 | Jul 5 12:13 | test_ws.c | |
| l | rwxr-xr-x | 1 | userk | staff | 13 | Sep 23 11:43:44 | 2023 test_script | ../test_ws.py |
| - | rw-r--r-- | 1 | userk | staff | 748 | Jul 5 12:13:13 | 2023 test_ws.c | |
+-------+-----------+------------+--------+--------+-------+-----------------+------------------+---------------+
After testing and review,
user1 concludes
The content of "ls -l" command for both Linux and Unix-like macOS has the same structure.
Therefore, textfsm_template_to_parse_linux_ls_l_output template can reuse to parse result for "ls -l" command line.
The content structure of "ls -lT" command of Unix-like macOS has addition column that hold year-value of file timestamp.
Therefore, snippet_to_parse_linux_ls_l_output needs to modify to meet requirement of "ls -lT" command.
user1 proposes two solutions to
userk.
Solution A: Using Separated Solution for Each Command
Reusing textfsm_template_to_parse_linux_ls_l_output for "ls -l" command of Unix-like macOS
Using below snippet solution to generate TextFSM template for "ls -lT" command of Unix-like macOS
----------
start() letter(var_ftype, -)mixed_word(var_fperms) digits(var_hard_links) word(var_fowner) letters(var_fgroup) digits(var_fsize) mixed_word(var_date_n_time, 3_group_occurrences) mixed_words(var_file_name) data(->, or_empty) mixed_words(var_real_file, or_empty) end() -> record
Generated TextFSM template that dedicate to parse result for only "ls -lT"
----------
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-24 11:20
################################
Value ftype (([a-zA-Z])|-)
Value fperms ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value hard_links (\d+)
Value fowner ([a-zA-Z][a-zA-Z0-9]*)
Value fgroup ([a-zA-Z]+)
Value fsize (\d+)
Value date_n_time ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( +[\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*){3})
Value file_name ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)*)
Value real_file (((([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)*))|))
Start
^${ftype}${fperms} +${hard_links} +${fowner} +${fgroup} +${fsize} +${date_n_time} +${file_name}\s*(->|)\s*${real_file}$$ -> Record
Test Data of "ls -lT"
----------
lrwxr-xr-x 1 userk staff 13 Sep 23 11:43:44 2023 test_script -> ../test_ws.py
-rw-r--r-- 1 userk staff 748 Jul 5 12:13:13 2023 test_ws.c
Test result is
----------
Total-rows-count: 2
[{'ftype': 'l', 'fperms': 'rwxr-xr-x', 'hard_links': '1', 'fowner': 'userk', 'fgroup': 'staff', 'fsize': '13', 'date_n_time': 'Sep 23 11:43:44 2023', 'file_name': 'test_script', 'real_file': '../test_ws.py'}, {'ftype': '-', 'fperms': 'rw-r--r--', 'hard_links': '1', 'fowner': 'userk', 'fgroup': 'staff', 'fsize': '748', 'date_n_time': 'Jul 5 12:13:13 2023', 'file_name': 'test_ws.c', 'real_file': ''}]
or
Total-rows-count: 2
+-------+-----------+------------+--------+--------+-------+----------------------+-------------+---------------+
| ftype | fperms | hard_links | fowner | fgroup | fsize | date_n_time | file_name | real_file |
+-------+-----------+------------+--------+--------+-------+----------------------+-------------+---------------+
| l | rwxr-xr-x | 1 | userk | staff | 13 | Sep 23 11:43:44 2023 | test_script | ../test_ws.py |
| - | rw-r--r-- | 1 | userk | staff | 748 | Jul 5 12:13:13 2023 | test_ws.c | |
+-------+-----------+------------+--------+--------+-------+----------------------+-------------+---------------+
Solution B: Using Optimal Flexible Solution for Either ls -l or ls -T
User snippet for both "ls -l" or "ls -lT"
----------
start() letter(var_ftype, -)mixed_word(var_fperms) digits(var_hard_links) word(var_fowner) letters(var_fgroup) digits(var_fsize) mixed_word(var_date_n_time, 2_group_occurrences) digit(var_year, repetition_4, or_empty) mixed_words(var_file_name) data(->, or_empty) mixed_words(var_real_file, or_empty) end() -> record
Generated TextFSM template that should parse result for both "ls -l" or "ls -lT"
----------
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-24 10:54
################################
Value ftype (([a-zA-Z])|-)
Value fperms ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value hard_links (\d+)
Value fowner ([a-zA-Z][a-zA-Z0-9]*)
Value fgroup ([a-zA-Z]+)
Value fsize (\d+)
Value date_n_time ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( +[\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*){2})
Value year (((\d{4})|))
Value file_name ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)*)
Value real_file (((([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)*))|))
Start
^${ftype}${fperms} +${hard_links} +${fowner} +${fgroup} +${fsize} +${date_n_time}\s*${year} ${file_name}\s*(->|)\s*${real_file}$$ -> Record
Test data of "ls -l" and "ls -lT"
----------
lrwxr-xr-x 1 userk staff 13 Sep 23 11:43 test_script -> ../test_ws.py
-rw-r--r-- 1 userk staff 748 Jul 5 12:13 test_ws.c
lrwxr-xr-x 1 userk staff 13 Sep 23 11:43:44 2023 test_script -> ../test_ws.py
-rw-r--r-- 1 userk staff 748 Jul 5 12:13:13 2023 test_ws.c
Test result is
----------
Total-rows-count: 4
[{'ftype': 'l', 'fperms': 'rwxr-xr-x', 'hard_links': '1', 'fowner': 'userk', 'fgroup': 'staff', 'fsize': '13', 'date_n_time': 'Sep 23 11:43', 'year': '', 'file_name': 'test_script', 'real_file': '../test_ws.py'}, {'ftype': '-', 'fperms': 'rw-r--r--', 'hard_links': '1', 'fowner': 'userk', 'fgroup': 'staff', 'fsize': '748', 'date_n_time': 'Jul 5 12:13', 'year': '', 'file_name': 'test_ws.c', 'real_file': ''}, {'ftype': 'l', 'fperms': 'rwxr-xr-x', 'hard_links': '1', 'fowner': 'userk', 'fgroup': 'staff', 'fsize': '13', 'date_n_time': 'Sep 23 11:43:44', 'year': '2023', 'file_name': 'test_script', 'real_file': '../test_ws.py'}, {'ftype': '-', 'fperms': 'rw-r--r--', 'hard_links': '1', 'fowner': 'userk', 'fgroup': 'staff', 'fsize': '748', 'date_n_time': 'Jul 5 12:13:13', 'year': '2023', 'file_name': 'test_ws.c', 'real_file': ''}]
or
Total-rows-count: 4
+-------+-----------+------------+--------+--------+-------+-----------------+------+-------------+---------------+
| ftype | fperms | hard_links | fowner | fgroup | fsize | date_n_time | year | file_name | real_file |
+-------+-----------+------------+--------+--------+-------+-----------------+------+-------------+---------------+
| l | rwxr-xr-x | 1 | userk | staff | 13 | Sep 23 11:43 | | test_script | ../test_ws.py |
| - | rw-r--r-- | 1 | userk | staff | 748 | Jul 5 12:13 | | test_ws.c | |
| l | rwxr-xr-x | 1 | userk | staff | 13 | Sep 23 11:43:44 | 2023 | test_script | ../test_ws.py |
| - | rw-r--r-- | 1 | userk | staff | 748 | Jul 5 12:13:13 | 2023 | test_ws.c | |
+-------+-----------+------------+--------+--------+-------+-----------------+------+-------------+---------------+
If userk decides to use Solution-A, user1 MIGHT provide the least effort to explain to userk such as
mixed_word(var_date_n_time, 2_group_occurrences) would capture exact three mixed words
e.g., Sep 23 11:43
Jul 5 12:13
However, output of "ls -lT" produces extra "year" data, they are Sep 23 11:43:44 2023
Jul 5 12:13:13 2023
To capture exact four mixed words for date_n_time variable, just modify 2 to 3
or
mixed_word(var_date_n_time, 3_group_occurrences)
If userk decides to use Solution-B, user1 MIGHT provide the least effort to explain to userk such as
output of "ls -lT" produces extra "year" data, they are Sep 23 11:43:44 2023
Jul 5 12:13:13 2023
If both "ls -l" and "ls -lT" is presented as tabular data,
the interpretion of "ls -l" is the tabular data of 10 columns where "year" column has all empty value
WHILE
the interpretion of "ls -lT" is the tabular data of 10 columns where "year" has some values which are four digits.
Therefore, the properties of the "year" column are
- MUST either have value or empty.
- A value MUST be four digits.
- A value MUST be next to date_n_time column.
As a result, it should be created and inserted right after date_n_time column as
... mixed_word(var_date_n_time, 2_group_occurrences) digit(var_year, repetition_4, or_empty) mixed_words(var_file_name) ...
Next example shall use deductive reasoning to troubleshot problem.
Assuming end-user group finds some added-value in
TextFSM template and really want to apply it to improve quality and productivity for their products. However, end-user group faces some challenges
TextFSM MIGHT requires
- Understanding TextFSM and ability to create TextFSM template.
- Understanding Python regular expression and ability to use it.
End-user Group's Advantage
- Surplus knowlege of test data. In other words, all members (i.e., 100%) of end-user group have solid knowledge about test data.
End-user Group's Disadvantage
- Around 3% members understand TextFSM and can build its template.
- Around 5% members understand Python regular express and know how to apply it.
End-user Group Expectation
- Expecting all members can confidently create TextFSM templates and use them daily.
End-user Group's Challenges
- Needing a TextFSM training for 97-100% members.
- Needing a Python regular express training for 95-100% members.
- Training process should help
+ To accelerate time to proficiency.
+ To increase knowledge retention.
+ To boost quality and productivity.
+ To deliver consistent outcome.
+ Etc.
To deal with these challenges, end-user group asks one member to research and to evaluate any product that can solve these challenges. Let's call member's name is
Tomy who have some TextFSM experience. Furthermore,
Tomy is a Python regular expression expertise.
Assuming
Tomy finds out that TemplateApp can solves these challenges and begins to evaluate it
Studying Test Data #1
Test Data
----------
a b
-------- -------
val1.1 val1.2
val2.2
val3.1
val4.1 val4.2
val5.1
Generated Snippet by Using Template Builder - Tabular - Symbol Divider
----------
# Non-commercial use: generated by WebTemplate v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-25 10:50
################################
a b
start() mixed_word(var_a) mixed_word(var_b) end(space) -> record
start() mixed_word(var_a) end(space) -> record
start() space(repetition_7_9) mixed_word(var_b) end(space) -> record
Generated Template is
----------
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-25 10:50
################################
Value a ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value b ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Start
^a +b
^${a} +${b} *$$ -> Record
^${a} *$$ -> Record
^ {7,9} ${b} *$$ -> Record
Test Result is
----------
Total-rows-count: 5
[{'a': 'val1.1', 'b': 'val1.2'}, {'a': '', 'b': 'val2.2'}, {'a': 'val3.1', 'b': ''}, {'a': 'val4.1', 'b': 'val4.2'}, {'a': 'val5.1', 'b': ''}]
or
Total-rows-count: 5
+--------+--------+
| a | b |
+--------+--------+
| val1.1 | val1.2 |
| | val2.2 |
| val3.1 | |
| val4.1 | val4.2 |
| val5.1 | |
+--------+--------+
Studying Test Data #2
Test Data
----------
a b
-------- -------
val1.1 1.2
2.2
val3.1
val4.1 4.2
val5.1
Generated Snippet by Using Template Builder - Tabular - Symbol Divider
----------
# Non-commercial use: generated by WebTemplate v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-25 11:17
################################
a b
start() mixed_word(var_a) number(var_b) end(space) -> record
start() mixed_word(var_a) end(space) -> record
start() space(repetition_7_9) number(var_b) end(space) -> record
Generated Template is
----------
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-25 11:17
################################
Value a ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value b (\d*[.]?\d+)
Start
^a +b
^${a} +${b} *$$ -> Record
^${a} *$$ -> Record
^ {7,9} ${b} *$$ -> Record
Test Result is
----------
Total-rows-count: 5
[{'a': 'val1.1', 'b': '1.2'}, {'a': '', 'b': '2.2'}, {'a': 'val3.1', 'b': ''}, {'a': 'val4.1', 'b': '4.2'}, {'a': 'val5.1', 'b': ''}]
or
Total-rows-count: 5
+--------+-----+
| a | b |
+--------+-----+
| val1.1 | 1.2 |
| | 2.2 |
| val3.1 | |
| val4.1 | 4.2 |
| val5.1 | |
+--------+-----+
Studying Test Data #1.1 - with Comment Column
Test Data
----------
a b comment
-------- ------- --------------------
val1.1 val1.2 first_line_has_all_values
val2.2 second line has 1st empty cell.
val3.1 third line has 2nd empty cell.
val4.1 val4.2 fourth line has all values.
val5.1 fifth line has 2nd empty cell.
Generated Snippet by Using Template Builder - Tabular - Symbol Divider
----------
# Non-commercial use: generated by WebTemplate v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-25 14:35
################################
a b comment
start() mixed_word(var_a) mixed_word(var_b) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
start() mixed_word(var_a) space(repetition_8_11) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
start() space(repetition_7_9) mixed_word(var_b) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
Generated Template is
----------
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-25 14:35
################################
Value a ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value b ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value comment ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*){,5})
Start
^a +b +comment
^${a} +${b} +${comment}$$ -> Record
^${a} {8,11} ${comment}$$ -> Record
^ {7,9} ${b} +${comment}$$ -> Record
Test Result is
----------
Total-rows-count: 5
[{'a': 'val1.1', 'b': 'val1.2', 'comment': 'first_line_has_all_values'}, {'a': '', 'b': 'val2.2', 'comment': 'second line has 1st empty cell.'}, {'a': 'val3.1', 'b': 'third', 'comment': 'line has 2nd empty cell.'}, {'a': 'val4.1', 'b': 'val4.2', 'comment': 'fourth line has all values.'}, {'a': 'val5.1', 'b': 'fifth', 'comment': 'line has 2nd empty cell.'}]
or
Total-rows-count: 5
+--------+--------+---------------------------------+
| a | b | comment |
+--------+--------+---------------------------------+
| val1.1 | val1.2 | first_line_has_all_values |
| | val2.2 | second line has 1st empty cell. |
| val3.1 | third | line has 2nd empty cell. |
| val4.1 | val4.2 | fourth line has all values. |
| val5.1 | fifth | line has 2nd empty cell. |
+--------+--------+---------------------------------+
Reviewing Test Result of #1.1
Expecting result
[
{'a': 'val1.1', 'b': 'val1.2', 'comment': 'first_line_has_all_values'},
{'a': '', 'b': 'val2.2', 'comment': 'second line has 1st empty cell.'},
{'a': 'val3.1', 'b': '', 'comment': 'third line has 2nd empty cell.'},
{'a': 'val4.1', 'b': 'val4.2', 'comment': 'fourth line has all values.'},
{'a': 'val5.1', 'b': '', 'comment': 'fifth line has 2nd empty cell.'}
]
but, received unexpected value in "b" column and dropping the first word in "comment" column on row #3 and row #5.
[
{'a': 'val1.1', 'b': 'val1.2', 'comment': 'first_line_has_all_values'},
{'a': '', 'b': 'val2.2', 'comment': 'second line has 1st empty cell.'},
{'a': 'val3.1', 'b': 'third', 'comment': 'line has 2nd empty cell.'},
{'a': 'val4.1', 'b': 'val4.2', 'comment': 'fourth line has all values.'},
{'a': 'val5.1', 'b': 'fifth', 'comment': 'line has 2nd empty cell.'}
]
Studying Test Data #2.1 - with Comment Column
Test Data
----------
a b comment
-------- ------- --------------------
val1.1 1.2 first_line_has_all_values
2.2 second line has 1st empty cell.
val3.1 third line has 2nd empty cell.
val4.1 4.2 fourth line has all values.
val5.1 fifth line has 2nd empty cell.
Generated Snippet by Using Template Builder - Tabular - Symbol Divider
----------
# Non-commercial use: generated by WebTemplate v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-25 15:18
################################
a b comment
start() mixed_word(var_a) number(var_b) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
start() mixed_word(var_a) space(repetition_8_11) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
start() space(repetition_7_9) number(var_b) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
Generated Template is
----------
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-25 15:18
################################
Value a ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value b (\d*[.]?\d+)
Value comment ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*){,5})
Start
^a +b +comment
^${a} +${b} +${comment}$$ -> Record
^${a} {8,11} ${comment}$$ -> Record
^ {7,9} ${b} +${comment}$$ -> Record
Test Result is
----------
Total-rows-count: 5
[{'a': 'val1.1', 'b': '1.2', 'comment': 'first_line_has_all_values'}, {'a': '', 'b': '2.2', 'comment': 'second line has 1st empty cell.'}, {'a': 'val3.1', 'b': '', 'comment': 'third line has 2nd empty cell.'}, {'a': 'val4.1', 'b': '4.2', 'comment': 'fourth line has all values.'}, {'a': 'val5.1', 'b': '', 'comment': 'fifth line has 2nd empty cell.'}]
or
Total-rows-count: 5
+--------+-----+---------------------------------+
| a | b | comment |
+--------+-----+---------------------------------+
| val1.1 | 1.2 | first_line_has_all_values |
| | 2.2 | second line has 1st empty cell. |
| val3.1 | | third line has 2nd empty cell. |
| val4.1 | 4.2 | fourth line has all values. |
| val5.1 | | fifth line has 2nd empty cell. |
+--------+-----+---------------------------------+
Reviewing Test Result of #2.1
Even though the test result of #2.1 delivers the expected outcome,
but Tomy CAN NOT figure out that this case is workable,
but the other case (i.e., #1.1) produces incorrect result.
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-25 14:35
################################
Value a ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value b ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value comment ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*){,5})
Start
^a +b +comment
^${a} +${b} +${comment}$$ -> Record
^${a} {8,11} ${comment}$$ -> Record
^ {7,9} ${b} +${comment}$$ -> Record
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-25 15:18
################################
Value a ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value b (\d*[.]?\d+)
Value comment ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*){,5})
Start
^a +b +comment
^${a} +${b} +${comment}$$ -> Record
^${a} {8,11} ${comment}$$ -> Record
^ {7,9} ${b} +${comment}$$ -> Record
Tomy tries several efforts to resolve incorrectness of parsing test data #1.1 such as
- manually create TextFSM template and test it.
- or ask other member to create TextFSM template and test it.
- or ask question in TextFSM forum for support.
After a few tries with some solutions, unfortunately, problem is still persisted.
#####
# Assuming, below template is manually created by
# other member from Tomy group for test data #1.1
#####
Value a (\S+)
Value b (\S+)
Value comment (\S+( \S+)*)
Start
^a +b +comment
^${a} +${b} +${comment}$$ -> Record
^${a} {10,} ${comment}$$ -> Record
^ {9,} ${b} +${comment}$$ -> Record
#####
# Assuming, below template is manually created by
# other member from Tomy group for test data #2.1
#####
Value a (\S+)
Value b (\d+\.?\d*)
Value comment (\S+( \S+)*)
Start
^a +b +comment
^${a} +${b} +${comment}$$ -> Record
^${a} {10,} ${comment}$$ -> Record
^ {9,} ${b} +${comment}$$ -> Record
Tomy discusses current situation with team and asks for open-minded ideas. One member suggests,
Opinion: this problem is about text and how to process it.
Is it possible to solve it by describing problem in plain text with logical thinking?
Assuming
Tomy agrees that this suggestion is reasonable and decides to hire
Reasoning Analyzer or
Reasoning Problem Solver. Let's call this person name is
Lucy.
Lucy
Strength
--------
- Ability to solve problem in plain text conversation with logical thinking.
Weakness
--------
- Aware about Python regular expression but don't know how it work.
- Have zero percent hand-on experience with Python regular expression.
Collaboration Requirements for Solving Problem
--------
- Need to provide problem statement in everyday conversation form with minimal technical details as much as possible.
Tommy's Work ...
Step #1: Converting Tech Work to Everyday Conversation
----------
Converting TextFSM template to everyday conversation might be complex.
Tomy finds out that user snippet which generated from TemplateApp
or WebTemplate is closed to human interpretion. Tomy decides to reuse it.
To make snippet more easier to identify between tech work and everyday conversation,
Tomy modifies user snippets in group of name mnemonics or chunking.
+ Replacing a blank space to space()
+ Replacing double spaces or multi-spaces to spaces()
+ Comment column can have one word or more,
mixed_word(var_comment, at_most_5_phrase_occurrences) will limit from one to six mixed-words,
need to modify to
mixed_words(var_comment) which will satisfy at least one mixed-word.
User snippet for test data #1.1
----------
a b comment
start() mixed_word(var_a) mixed_word(var_b) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
start() mixed_word(var_a) space(repetition_8_11) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
start() space(repetition_7_9) mixed_word(var_b) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
After modifying into group of name mnemonics or chunking.
a b comment
start() mixed_word(var_a)spaces()mixed_word(var_b)spaces()mixed_words(var_comment) end() -> record
start() mixed_word(var_a)space()space(repetition_8_11)space()mixed_words(var_comment) end() -> record
start() space(repetition_7_9)space()mixed_word(var_b)spaces()mixed_words(var_comment) end() -> record
User snippet for test data #2.1
----------
a b comment
start() mixed_word(var_a) number(var_b) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
start() mixed_word(var_a) space(repetition_8_11) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
start() space(repetition_7_9) number(var_b) mixed_word(var_comment, at_most_5_phrase_occurrences) end() -> record
After modifying into group of name mnemonics or chunking.
a b comment
start() mixed_word(var_a)spaces()number(var_b)spaces()mixed_words(var_comment) end() -> record
start() mixed_word(var_a)space()space(repetition_8_11)space()mixed_words(var_comment) end() -> record
start() space(repetition_7_9)space()number(var_b)spaces()mixed_words(var_comment) end() -> record
Tommy's Work ...
Step #2: Organizing Data For Statement Problem
----------
Given Two Set Of Test Data and User Snippet
test_data_1
----------
a b comment
-------- ------- --------------------
val1.1 val1.2 first_line_has_all_values
val2.2 second line has 1st empty cell.
val3.1 third line has 2nd empty cell.
val4.1 val4.2 fourth line has all values.
val5.1 fifth line has 2nd empty cell.
user_snippet_1
----------
a b comment
start() mixed_word(var_a)spaces()mixed_word(var_b)spaces()mixed_words(var_comment) end() -> record
start() mixed_word(var_a)space()space(repetition_8_11)space()mixed_words(var_comment) end() -> record
start() space(repetition_7_9)space()mixed_word(var_b)spaces()mixed_words(var_comment) end() -> record
test_data_2
----------
a b comment
-------- ------- --------------------
val1.1 1.2 first_line_has_all_values
2.2 second line has 1st empty cell.
val3.1 third line has 2nd empty cell.
val4.1 4.2 fourth line has all values.
val5.1 fifth line has 2nd empty cell.
user_snippet_2
----------
a b comment
start() mixed_word(var_a)spaces()number(var_b)spaces()mixed_words(var_comment) end() -> record
start() mixed_word(var_a)space()space(repetition_8_11)space()mixed_words(var_comment) end() -> record
start() space(repetition_7_9)space()number(var_b)spaces()mixed_words(var_comment) end() -> record
Problem
XYZ system takes pair(test_data_1, user_snippet1) and expect to produce below result
+--------+--------+---------------------------------+
| a | b | comment |
+--------+--------+---------------------------------+
| val1.1 | val1.2 | first_line_has_all_values |
| | val2.2 | second line has 1st empty cell. |
| val3.1 | | third line has 2nd empty cell. |
| val4.1 | val4.2 | fourth line has all values. |
| val5.1 | | fifth line has 2nd empty cell. |
+--------+--------+---------------------------------+
but the actual result is that some values are removed from "comment" column and those removed values are inserted into "b" column.
+--------+--------+---------------------------------+
| a | b | comment |
+--------+--------+---------------------------------+
| val1.1 | val1.2 | first_line_has_all_values |
| | val2.2 | second line has 1st empty cell. |
| val3.1 | third | line has 2nd empty cell. |
| val4.1 | val4.2 | fourth line has all values. |
| val5.1 | fifth | line has 2nd empty cell. |
+--------+--------+---------------------------------+
XYZ system takes pair(test_data_2, user_snippet2) and expect to produce below result
+--------+-----+---------------------------------+
| a | b | comment |
+--------+-----+---------------------------------+
| val1.1 | 1.2 | first_line_has_all_values |
| | 2.2 | second line has 1st empty cell. |
| val3.1 | | third line has 2nd empty cell. |
| val4.1 | 4.2 | fourth line has all values. |
| val5.1 | | fifth line has 2nd empty cell. |
+--------+-----+---------------------------------+
good news is that XYZ system produces the expected result.
Tommy's Work ...
Step #3: Creating Statement Problem
----------
Problem Statement 1:
Find a root cause that
+ the good result was produced from pair(test_data_2, user_snippet_2),
+ but the bad result was produced from pair(test_data_1, user_snippet_1).
Problem Statement 2:
Find a root cause that the incorrect result is produced from pair(test_data_1, user_snippet_1).
Tommy's Work ...
Step #4: Creating Cheat Sheet To Explain Technical Terms
----------
Keywords Description
------------------- --------------------------------------------------
start telling system to search at begining.
end telling system to stop searching.
mixed_word telling system to mach at least one alphabet number character,
other characters are printable characters such as letters, digits, or punctuations.
For example, "a", "1.2.3.4", "(a)" are mixed-word.
++++++++++
"-", "+++---" are NOT mixed-word because they don't
contain at least one alphabet number character.
mixed_words telling system to match at least one mix-word and separator between
mixed-word is a blank space character.
In other words, mixed-words is a group of mixed-word separating by a blank space.
For example, "a", "1.2.3.4", "yellow pencil." are mixed-words.
++++++++++
"yellow pencil." are NOT mixed-words because
separator requirement of mix-words is a blank space character (i.e., ).
In this case, separator between "yellow" and "pencil."
triple-blank-space (i.e., ) which is not met mix-words separator requirement.
"yellow - pencil." are NOT mixed-words because
second word (that is hyphen character or "-")
doesn't contain at least one alphabet number character.
number telling system to match digits or floating point.
For example, "1", "123', "123.456" are number.
space telling system to match a blank space character.
spaces telling system to match at least one blank space.
Arguments Description
------------------- --------------------------------------------------
var_<name> telling system to store a matching to variable <name>
repetition_<m>_<n> telling system to repeat matching from <m> to <n> times.
Lucy's Work ...
Step #1: Simplifying User Snippet For Better Recognition
After discussing with Tomy, Lucy organizes user snippet for more human readable such as,
user_snippet_1
----------
start() mixed_word(var_a) spaces() mixed_word(var_b) spaces() mixed_words(var_comment) end()
start() mixed_word(var_a) space() space(repetition_8_11) space() mixed_words(var_comment) end()
start() space(repetition_7_9) space() mixed_word(var_b) spaces() mixed_words(var_comment) end()
user_snippet_2
----------
start() mixed_word(var_a) spaces() number(var_b) spaces() mixed_words(var_comment) end()
start() mixed_word(var_a) space() space(repetition_8_11) space() mixed_words(var_comment) end()
start() space(repetition_7_9) space() number(var_b) spaces() mixed_words(var_comment) end()
Lucy's Work ...
Step #2: Customizing Test Data For Better Investigating Problem
Since problem happened at line #3 and #5, only use those data for investigation.
test_data_1
a b comment
-------- ------- --------------------
...
val3.1 third line has 2nd empty cell.
...
val5.1 fifth line has 2nd empty cell.
test_data_2
a b comment
-------- ------- --------------------
...
val3.1 third line has 2nd empty cell.
...
val5.1 fifth line has 2nd empty cell.
Lucy collaborates with Tomy to find a root cause ...
Step #3: Reasoning to Find a Root Cause for Problem Statement 1
Since pair(test_data_2, user_snippet_2 produces the correct result,
Lucy might begin with this pair because its result might be a baseline result
for incorrect result. Assuming Lucy analyzes this pair.
test_data_2
a b comment
-------- ------- --------------------
...
val3.1 third line has 2nd empty cell.
...
val5.1 fifth line has 2nd empty cell.
user_snippet_2
----------
start() mixed_word(var_a) spaces() number(var_b) spaces() mixed_words(var_comment) end()
start() mixed_word(var_a) space() space(repetition_8_11) space() mixed_words(var_comment) end()
start() space(repetition_7_9) space() number(var_b) spaces() mixed_words(var_comment) end()
Lucy asks:
Tomy, can you explain how to begin?
Tomy replies:
XYZ system will pick the first line of user_snippet_2 and then process.
start() mixed_word(var_a) spaces() number(var_b) spaces() mixed_words(var_comment) end()
Lucy observes and then asks:
start() mixed_word(var_a)
It seems XYZ system will look for mixed-word at beginining.
Is "val3.1" a mixed-word?
Tomy replies:
Yes, it is.
Lucy observes and then asks:
... mixed_word(var_a) spaces()
Is there at least one blank space after "val3.1"
Tomy replies:
Yes, it is. It should have at least 1 blank space and at most 8 blank spaces after "val3.1".
Lucy observes and then asks:
... spaces() number(var_b)
Is there any number after "val3.1" and multiple blank spaces?
Tomy replies:
No, "third" is a word. It can't be number.
Lucy asks:
It is a failed case. What next?
Tomy replies:
XYZ system will pick the next line of user_snippet_2 (i.e., second line) and then process.
start() mixed_word(var_a) space() space(repetition_8_11) space() mixed_words(var_comment) end()
Lucy asks:
start() mixed_word(var_a)
Is "val3.1" a mixed-word?
Tomy replies:
Yes.
Lucy asks:
... mixed_word(var_a) space() space(repetition_8_11) space()
Calculating: 1-space + range(8, 11)-space + 1-space
should be equal to range(10, 13)-space
or should be equal to at least 10-space or at most 13-space
Is there around 10 to 13 blank spaces after "val3.1"?
Tomy replies:
Yes.
Lucy asks:
... space() space(repetition_8_11) space() mixed_words(var_comment)
Is there mixed-words after 10 to 13 blank spaces?
Tomy replies:
Yes, "third line has 2nd empty cell." is mixed-words.
...
... conversation is continued ...
At the end, both Tomy and Lucy know that the second line of user_snippet_2 should parse below data correctly.
That is ...
start() mixed_word(var_a) space() space(repetition_8_11) space() mixed_words(var_comment) end()
a b comment
-------- ------- --------------------
...
val3.1 third line has 2nd empty cell.
...
val5.1 fifth line has 2nd empty cell.
test_data_1
a b comment
-------- ------- --------------------
...
val3.1 third line has 2nd empty cell.
...
val5.1 fifth line has 2nd empty cell.
user_snippet_1
----------
start() mixed_word(var_a) spaces() mixed_word(var_b) spaces() mixed_words(var_comment) end()
start() mixed_word(var_a) space() space(repetition_8_11) space() mixed_words(var_comment) end()
start() space(repetition_7_9) space() mixed_word(var_b) spaces() mixed_words(var_comment) end()
Next, Lucy and Tomy continue to find root cause of on pair(test_data_1, user_snippet_1)
where the first line of user_snippet_1 is
start() mixed_word(var_a) spaces() mixed_word(var_b) spaces() mixed_words(var_comment) end()
Lucy asks:
start() mixed_word(var_a)
Is "val3.1" a mixed-word?
Tomy replies:
Yes.
Lucy asks:
... mixed_word(var_a) spaces()
Is there at least one blank space after "val3.1"
Tomy replies:
Yes.
Lucy asks:
... spaces() mixed_word(var_b)
Is there a mixed-word after "val3.1" and multiple blank spaces?
Tomy replies:
Yes, there is a word after "val3.1" and multiple blank spaces. That word is "third".
But NO, because "third" word supposes to be a first word in "comment" column.
Now, it incorrectly assigns to "b" column.
Lucy explains:
Based on the sequence of
start mixed-word spaces mixed-word spaces mixed-words end
where spaces is interpreted as one-or-more-spaces (i.e., at least one blank space)
can be rewritten as
start mixed-word one-or-more-spaces mixed-word one-or-more-spaces mixed-words end
Therefore, the first snippet line of user_snippet_1 should be the following data for test_data_1
start mixed-word one-or-more-spaces mixed-word one-or-more-spaces mixed-words end
"val1.1" " " "val1.2" " " "first_line_has_all_values"
"val3.1" " " "third" " " "line has 2nd empty cell."
"val4.1" " " "val4.2" " " "fourth line has all values."
"val5.1" " " "fifth" " " "line has 2nd empty cell."
Lucy continues:
Let's talk about pair(test_data_2, user_snippet_2).
Based testing result, the pair(test_data_2, user_snippet_2) is produced correct result.
Actually, this pair(test_data_2, user_snippet_2) is RANDOMLY produced correct result
because all first word in "comment" column is a word or mixed-word which is distinguished with number.
However, if a first word in "comment" column becomes number,
then pair(test_data_2_suggested_by_Lucy, user_snippet_2) should produce incorrect result.
test_data_2_suggested_by_Lucy
a b comment
-------- ------- --------------------
val1.1 1.2 first_line_has_all_values
2.2 second line has 1st empty cell.
val3.1 3 rd line has 2nd empty cell.
val4.1 4.2 fourth line has all values.
val5.1 5 th line has 2nd empty cell.
user_snippet_2
----------
a b comment
start() mixed_word(var_a) number(var_b) mixed_words(var_comment) end() -> record
start() mixed_word(var_a) space(repetition_8_11) mixed_words(var_comment) end() -> record
start() space(repetition_7_9) number(var_b) mixed_words(var_comment) end() -> record
Test Result
----------
+--------+-----+---------------------------------+
| a | b | comment |
+--------+-----+---------------------------------+
| val1.1 | 1.2 | first_line_has_all_values |
| | 2.2 | second line has 1st empty cell. |
| val3.1 | 3 | rd line has 2nd empty cell. |
| val4.1 | 4.2 | fourth line has all values. |
| val5.1 | 5 | th line has 2nd empty cell. |
+--------+-----+---------------------------------+
Tomy performs hand-on test to confirm Lucy's finding:
>>>
>>> # start() mixed_word(var_a) number(var_b) mixed_words(var_comment) end()
>>> # rewritten to name mnemonics or chunking style
>>> # start()mixed_word(var_a)spaces()number(var_b)spaces()mixed_words(var_comment)end()
>>> # rewritten to human readable language
>>> # {start}{mixed_word_a}{one_or_more_spaces}{number_b}{one_or_more_spaces}{mixed_words_comment}{end}
>>> pattern_format = "{start}{mixed_word_a}{one_or_more_spaces}{number_b}{one_or_more_spaces}{mixed_words_comment}{end}"
>>>
>>> start = "^"
>>> end = "$"
>>> mixed_word = "[\\x21-\\x7e]*[a-zA-Z0-9][\\x21-\\x7e]*"
>>> number = "\\d*[.]?\\d+"
>>> one_or_more_spaces = " +"
>>>
>>> mixed_word_a = "(?P<a>{mixed_word})".format(mixed_word=mixed_word)
>>> number_b = "(?P<b>{number})".format(number=number)
>>> mixed_words_comment = "(?P<comment>{mixed_word}( {mixed_word})*)".format(mixed_word=mixed_word)
>>>
>>> pattern = pattern_format.format(
... start=start,
... end=end,
... mixed_word_a=mixed_word_a,
... mixed_words_comment=mixed_words_comment,
... number_b=number_b,
... one_or_more_spaces=one_or_more_spaces
... )
>>>
>>> print(pattern)
^(?P<a>[\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*) +(?P<b>\d*[.]?\d+) +(?P<comment>[\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)*)$
>>>
>>> import re
>>>
>>> # expecting pattern won't match test data.
>>> test_data = "val3.1 third line has 2nd empty cell."
>>> result = re.search(pattern, test_data)
>>> print(result)
None
>>>
>>> # expecting pattern matches test_data_suggested_by_lucy
>>> test_data_suggested_by_lucy = "val3.1 3 rd line has 2nd empty cell."
>>> result = re.search(pattern, test_data_suggested_by_lucy)
>>> print(result)
<re.Match object; span=(0, 46), match='val3.1 3 rd line has 2nd empty cell.'>
>>> print(result.groupdict())
{'a': 'val3.1', 'b': '3', 'comment': 'rd line has 2nd empty cell.'}
>>>
After tested Lucy's finding, Tomy agree with Lucy that
pair(test_data_2, user_snippet_2) is NOT ALWAYS produced correct result
because a first word of "comment" column can be anything such as:
letter(s), number, word, mixed-word, punctuation(s), etc.,.
Lucy continues to investigate second problem ...
Step #4: Reasoning to Find a Root Cause for Problem Statement 2
Since problem happened at first line of either user_snippet_1 or user_snippeet_2,
let's focus on a first line snippet
start() mixed_word(var_a) spaces() mixed_word(var_b) spaces() mixed_words(var_comment) end()
...
start() mixed_word(var_a) spaces() number(var_b) spaces() mixed_words(var_comment) end()
Lucy analyses blank-spaces definition:
spaces is interpreted as matching at least one blank space, or
matching one or more spaces.
In logic thinking,
"at least one ..." or "one or more ... "
implies
"as many as possible", or "infinite quantities"
Lucy adds notes:
start() mixed_word(var_a) spaces(<infinite quantities>) mixed_word(var_b) spaces(<infinite quantities>) mixed_words(var_comment) end()
...
start() mixed_word(var_a) spaces(<infinite quantities>) number(var_b) spaces(<infinite quantities>) mixed_words(var_comment) end()
Lucy asks:
Is there infinite blank spaces between "a" and "b" columns?
Is there infinite blank spaces between "b" and "comment" columns?
Tomy responses:
No, it should be at least one blank space and at most eight blank spaces between "a" and "b" columns.
And, it should be at least one blank space and at most eight blank spaces between "b" and "comment" columns.
Lucy explains:
Actual structure (or, skeleton) of content have finitie blank spaces quantities, but some of them
have used infinite blank spaces quantities which cause to transform current structure
to different structure.
The problem should be corrected if finite quantities apply accordingly.
Tomy work ...
Step #5: Correcting Problem for user_snippet_1 and test_data_1
User Snippet
----------
a b comment
start() mixed_word(var_a) space(repetition__7)mixed_word(var_b) space(repetition__7)mixed_words(var_comment) end() -> record
start() mixed_word(var_a) space(repetition_8_11) mixed_words(var_comment) end() -> record
start() space(repetition_7_9) mixed_word(var_b) space(repetition__7)mixed_words(var_comment) end() -> record
Generated TextFSM template
----------
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-27 16:49
################################
Value a ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value b ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value comment ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)*)
Start
^a +b +comment
^${a} {,7}${b} {,7}${comment}$$ -> Record
^${a} {8,11} ${comment}$$ -> Record
^ {7,9} ${b} {,7}${comment}$$ -> Record
Test Data
----------
a b comment
-------- ------- --------------------
val1.1 val1.2 first_line_has_all_values
val2.2 second line has 1st empty cell.
val3.1 third line has 2nd empty cell.
val4.1 val4.2 fourth line has all values.
val5.1 fifth line has 2nd empty cell.
Test Result
----------
Total-rows-count: 5
[{'a': 'val1.1', 'b': 'val1.2', 'comment': 'first_line_has_all_values'}, {'a': '', 'b': 'val2.2', 'comment': 'second line has 1st empty cell.'}, {'a': 'val3.1', 'b': '', 'comment': 'third line has 2nd empty cell.'}, {'a': 'val4.1', 'b': 'val4.2', 'comment': 'fourth line has all values.'}, {'a': 'val5.1', 'b': '', 'comment': 'fifth line has 2nd empty cell.'}]
or
Total-rows-count: 5
+--------+--------+---------------------------------+
| a | b | comment |
+--------+--------+---------------------------------+
| val1.1 | val1.2 | first_line_has_all_values |
| | val2.2 | second line has 1st empty cell. |
| val3.1 | | third line has 2nd empty cell. |
| val4.1 | val4.2 | fourth line has all values. |
| val5.1 | | fifth line has 2nd empty cell. |
+--------+--------+---------------------------------+
Tomy work ...
Step #6: Correcting Problem for user_snippet_2 and test_data_2
User Snippet
----------
a b comment
start() mixed_word(var_a) space(repetition__7)number(var_b) space(repetition__7)mixed_words(var_comment) end() -> record
start() mixed_word(var_a) space(repetition_8_11) mixed_words(var_comment) end() -> record
start() space(repetition_7_9) number(var_b) space(repetition__7)mixed_words(var_comment) end() -> record
Generated TextFSM template
----------
# Non-commercial use: generated by TemplateApp v.0.1.13 (geekstrident.com)
# Created Date: 2023-09-27 16:56
################################
Value a ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)
Value b (\d*[.]?\d+)
Value comment ([\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*( [\x21-\x7e]*[a-zA-Z0-9][\x21-\x7e]*)*)
Start
^a +b +comment
^${a} {,7}${b} {,7}${comment}$$ -> Record
^${a} {8,11} ${comment}$$ -> Record
^ {7,9} ${b} {,7}${comment}$$ -> Record
Test Data
----------
a b comment
-------- ------- --------------------
val1.1 val1.2 first_line_has_all_values
val2.2 second line has 1st empty cell.
val3.1 third line has 2nd empty cell.
val4.1 val4.2 fourth line has all values.
val5.1 fifth line has 2nd empty cell.
Test Result
----------
Total-rows-count: 5
[{'a': 'val1.1', 'b': '1.2', 'comment': 'first_line_has_all_values'}, {'a': '', 'b': '2.2', 'comment': 'second line has 1st empty cell.'}, {'a': 'val3.1', 'b': '', 'comment': 'third line has 2nd empty cell.'}, {'a': 'val4.1', 'b': '4.2', 'comment': 'fourth line has all values.'}, {'a': 'val5.1', 'b': '', 'comment': 'fifth line has 2nd empty cell.'}]
or
Total-rows-count: 5
+--------+-----+---------------------------------+
| a | b | comment |
+--------+-----+---------------------------------+
| val1.1 | 1.2 | first_line_has_all_values |
| | 2.2 | second line has 1st empty cell. |
| val3.1 | | third line has 2nd empty cell. |
| val4.1 | 4.2 | fourth line has all values. |
| val5.1 | | fifth line has 2nd empty cell. |
+--------+-----+---------------------------------+
Tomy work ...
Step #7: Preparing Written Report for Team
During creating report for management team, Tomy might emphasize some advantages to boost train processes such as
- Leveraging the advantage of end-user group that all members are surplus knowlege of test data.
- End-users can build or describe plain text snippet to solve problem.
- When end-users tackle a problem, end-users can collaborate with other end-users to solve problem.