World: r3wp
[I'm new] Ask any question, and a helpful person will try to answer.
older newer | first last |
Henrik 19-Apr-2009 [1785] | I don't yet understand why a block would be easier to parse than lines, by easier do you mean more efficient or easier to create the code? Yes, it's easier, because REBOL is based around this concept. Without this concept, dialects wouldn't make much sense. Your configuration file shown above is a good candidate for a dialect with some tweaks. I suggest, you read again what I wrote above about the basics of words, context and meaning. I can't emphasize enough how important this is to REBOL and especially for block parsing. It's important to understand this before moving on, or REBOL will remain difficult to use for you. Or drop your parse project for now and stick with the basics until you understand more of REBOL. is there a list of things I can't expect to load? The LOAD function will error out, if a string (such as a file you read) can't be loaded into a block of data. Try these in the console, and see which ones work: load "hello" load "hello," load "hello." load "%" load "1 2 3 4" load "hostname pig interface Null0 ! interface Loopback58 description SLA changed this" load %/c/temp/cisco.txt |
sqlab 19-Apr-2009 [1786x2] | I am against loading this configuation files. Why? -you can not control what is inside we know already, that there are elements unloadable by Rebol and the description almost always needs string parsing What would I change? I would either use only one temp variable in the parse rule and after just set to the new variable, as there is already a copy involved or I would use a meaningfull variable name in the first place |
Another reason against loading - we can not determine, if "interface" is at the start of a line | |
mhinson 19-Apr-2009 [1788] | Good point about my temp1 temp2 etc. that was sloppy. It is true I cannot control what is inside the config files. They can contain any printable chars (eg in encrypted password fields or remarks/descriptions or embedded TCL code) and sometimes I am going to want to capture that text. I don't mind trying to do both methods as it will help me learn. Since I can't load the file directly I am thinking I will need to do a read %file.txt & replace the /\,[]%$()@:? with %xx etc. then load the result? I cant find a list of all the chars that I would need to treat like this yet. Henrik, I do continue to read what you have written, it is helpful & I think I am beginning to appreciate the concepts. I am probably not as clear as I should be about the specification of what I am trying to do so the code has tended towards listing the requirements rather than being elegant. Thanks /\/\ |
sqlab 19-Apr-2009 [1789] | further enhancements I would try to extract the rule parts into single rule e.g. interfacerule: [--] descriptionrule: [--] etc. (names are debatable.) better than [copy .. [" ip address" to end]] is probably [to "ip address" copy temp to end], unless you know, that there is always one space |
Sunanda 19-Apr-2009 [1790] | 'read/lines is not bad. It enables you to easily split the problem inyto smaller phases. It makes it harder to solve the problem in one huge 'parse. But maybe one big 'parse is not the best approach -- especially if you need (say)backtracking for error recovery, or line-numbers of points of failure. You are getting several people's views on how to tackle your problem here. Take their advice seriously, but remember you are the domain specialist, so you get to choose which solution fits best. Not us :-) |
mhinson 19-Apr-2009 [1791] | ok. I follow your extraction of rules idea & this is what you had in your original suggestion. Now I am getting more familiar with what I am looking at I can understand the benefit of that & will start to work that way now. [copy .. [" ip address" to end]] was to get the interface address in the interface section of the file. It is identified by 1) some line after the line containing "interface" 2) at the begining of the line always starting with one space before the word "ip address" 3) before any line with a non-blank first char unless it is a new instance of "interface" (hence my IntFlag which Steeve didn't like my method of use) I found from testing that [to "ip address" copy temp to end] or [to " ip address" copy temp to end] found the string anywhere in the line, but [copy .. [" ip address" to end]] only finds the string if it is at the start of the line which is what I was trying to achieve. Have I made a mistake here & need to retest my assumptions perhaps? I always appreciate lots of different views on issues so I am loving the multiple responses. Sunanda you have reminded me about line numbers. I will tackle them after the extraction of rules I think, as I want them in my output for data output quality & validation checking. I have been looking at your parse-ini.r to see how you have read a file into a Rebol block, but I may stick with read/line for a bit longer while get my head round parsing each line in turn. I get the impression that once I have a final block of code there will be someone who can turn it into 2 short lines including a built in Easter egg game. |
sqlab 19-Apr-2009 [1792] | No, you are right. If there is always one leading space after newline identifying a valid ip address, your approach is the best. I just don't know anything about the stringent syntax rules of your config files, hence my suggestion. |
mhinson 19-Apr-2009 [1793x2] | Thanks. These files are getting better with more recent versions of Cisco IOS but sometimes trial and error is the only way to find the formats used. |
I am still new and confused. where can I read about how to do this please? file: "%file.txt" host: "Router1" interface: "fa0" i: 25 description: [] ipaddr: "1.1.1.1 255.255.255.0" write/append/string %/c/temp/result.log [file tab i tab host tab interface tab description tab ipaddr newline] I want the output file to be a tab-seperated set of values but all I get is the text filetabitabhosttabinterfacetabdescriptiontabipaddrnewline | |
Oldes 19-Apr-2009 [1795x3] | write/append/string %/c/temp/result.log rejoin [file tab i tab host tab interface tab description tab ipaddr newline] |
andor just simple REDUCE instead of REJOIN should be enough in this case | |
Also you must use MOLD for the values, if you want to keep the type (for example the block as the description) | |
mhinson 19-Apr-2009 [1798x2] | Thanks very much I have seen reduce & rejoin & mold but didnt realise it was relevant to writing a file.. this is the first time I have ever written to a file. |
I have tried to understand & take on what I have been told, thanks. Is this worse or better. It does what I was looking to do & I know how to extend it in the same structure. I am sure it would be educational for me if anyone has time to tear it to shreds please. Should I stop using read/line now? Would I get the benefit still? Or is the requirement too fragmented for this approach now? Should I use functions anywhere instead? Have I initialised my variables in the right & appropriate way? filename: copy %/c/temp/cisco.txt ;; cisco config file outFile: copy %/c/temp/outFile.log ;; tab separated output hostname: copy [] interface: copy [] intDesc: copy [] intIpaddr: [] ipRoute: [] IntFlag: false spacer: charset " ^/" name-char: complement spacer lines: read/lines filename outInterface: [ write/append outFile reduce [filename tab i tab hostname tab interface tab intDesc tab intIpaddr newline] ] clearInterface: [ interface: copy [] intDesc: copy [] intIpaddr: [] ] interfaceRule: [ ["interface " copy temp-interface to end] ( ;; captures point-point as well if IntFlag outInterface ;; start of new interface section so output data collected previously. if IntFlag clearInterface interface: copy temp-interface print ["! found at line " i] ;; debug print current-line ;; debug IntFlag: true ) ] descRule: [ [" description " copy intDesc to end] ( if IntFlag [print current-line] ;; debug ) ] ipAddrRule: [[" ip address " copy intIpaddr to end] ( print current-line ;; debug ) ] hostnameRule: [["hostname " copy hostname to end] ( ;; "hostname" print current-line ;; debug ) ] iprouteRule: [copy iproute ["ip route" to end] ( ;; "ip route" print current-line ;; debug ) ] IntFlagRule: [copy tempZZ [name-char to end] ( ;; not space or newline. this must be out of the int section if IntFlag outInterface ;; end of interface section so output data collected. if IntFlag clearInterface if IntFlag [print "!"] ;; debug IntFlag: false ;; ) ] i: 0 foreach line lines [i: i + 1 ;; move through lines & track line number current-line: line ;; for debug output parse/all line [ ;; parse only using rules below interfaceRule ;; evaluated if "interface" found preceeded by nothing else | descRule ;; evaluate if " desc" found preceeded by nothing else | ipAddrRule ;; " ip address" | hostnameRule ;; " hostname" | iprouteRule ;; "ip route" | IntFlagRule ;; unset interface flag if no longer in interface section (no " ^/") ] ] | |
Graham 19-Apr-2009 [1800x7] | filename: copy %/c/temp/cisco.txt ;; cisco config file outFile: copy %/c/temp/outFile.log ;; tab separated output |
don't need 'copy there | |
what's this? | |
outInterface: [ write/append outFile reduce [filename tab i tab hostname tab interface tab intDesc tab intIpaddr newline] ] | |
should that be a function and not just a block? | |
same with clearinterface | |
which needs a 'copy on the last [ ] | |
Steeve 19-Apr-2009 [1807] | What the need of flags and splitted lines, uh ? you can't write simple semantic ? Reading, your example file , you've got these simple rules. 1/ counting the lines line: [ thru newline (n: n + 1)] 2/ one interface mays contain several lines (infos) and is terminated by a line beginning by "!" interface: [ "interface" copy interface* line any [infos | #"!" line break] ] 3/ infos may be description, ip-adrr, ip-tables infos: [ " description " copy desc* line | " ip route " copy route* line | "ip address" copy ip-add* line ] That''s all folks, just parse the whole file with: parse/all [any [interface | line]] Please don't use read/lines or internal flags for such simple rules. |
BrianH 20-Apr-2009 [1808] | The problem with that method is managing backtracking. If your lines are really separate, you will have to be careful in writing your rules to make sure that you don't inadvertantly backtrack to a previous line when you don't want to. |
Steeve 20-Apr-2009 [1809x2] | No, Backtracking is a wonderfull feature, it's not a problem. People who get unwanted backtracking, just don't know how to use parse correctly. |
but imho, it's easy to learn. | |
BrianH 20-Apr-2009 [1811x2] | Hello, welcome to the "I'm new" group. Let's assume that someone who is asking questions about parse here doesn't know parse :) |
I find it pretty easy to manage backtracking too, but I used to use Icon before REBOL. Most people without a background in backtracking parsers or languages tend to have a bit of trouble with backtracking. | |
mhinson 20-Apr-2009 [1813x2] | Thanks for pointing out the errors. The lines I want to group together are not all together in the file. But for the interface details they are. IP routes are grouped together under a vrf & the interfaces will relate to a particular vrf. The end of a section might be a "!" or might just be the beginning of the next section, or any non space or anything that does not match a pattern.. It depends on the particular section. I will try to reduce the number of rules I need and get a very clear view of what I am trying to achieve. I don't find the semantics of this very easy to grasp and I am still struggling to find any documentation that makes sense to me. Sorry to be asking so many questions but I not done any programming to speak of since Pascal the mid 1980s so I am sort of like a complete idiot as you see. Thanks for taking the time to suggest how much improvement is possible. |
another very basic question. how can I pass a filename from the command line please? filename: %/c/temp/file.txt works fine, but if I pass the filename from the command line it get surrounded by "" do I have to parse the result to get the filename, or is there a simpler way for something so common? The only reference I could find was here http://www.rebol.com/docs/sdk/custom.html#section-3 It seems there is a great deal of Rebol documentation, but simple questions can be had to find answers to. | |
BrianH 20-Apr-2009 [1815] | Try passing the string to TO-REBOL-FILE and then that will let you specify filenames with local file syntax. |
Sunanda 20-Apr-2009 [1816] | assuming the file name is a string in system/options/args filename: to-file system/options/args Though you may want to error trap that -- in case the command line is malformed. One way: filename: none attempt [ filename: to-file system/options/args] if none? file-name [print "Bad command line" halt] |
BrianH 20-Apr-2009 [1817] | Sunanda, you're showing your Unix or Linux usage there. TO-FILE doesn't make sense to use on Windows (note %/c/ in his example). |
mhinson 20-Apr-2009 [1818] | Thanks, that worked exactly as I needed, either way, & now it has helped me find the documentation for "datatype functions" which I am sure I will need more of later. |
Sunanda 20-Apr-2009 [1819x2] | Thanks for the correction, Brian. |
Mike, REBOL has some built-in help. Sometimes it can jog the memory, or point you to a function you never dreamed came as standard .... Try these in the console help file help "to" | |
mhinson 20-Apr-2009 [1821] | Thanks Sunanda, that is very handy, I didnt realise help searched like that, I thought you had to give it an exact command. very good. |
Oldes 20-Apr-2009 [1822] | Instead of: filename: none attempt [ filename: to-file system/options/args] if none? file-name [print "Bad command line" halt] I would use: if error? try [filename: to-file system/options/args][ print "Bad command line" halt ] I really don't like that people use the attemp in cases where they expect error. I use own attempt in cases where I don't expect error but still want to continue with execution (display and log the error). |
Sunanda 21-Apr-2009 [1823] | Help is even better in R3 -- worth getting a copy just for that: http://www.rebol.com/article/0404.html |
mhinson 21-Apr-2009 [1824] | That is very good and usefull thanks. Is there any way to get help on things like view layout [ slider ] please. I am paticularly keen to find how the data is returned from these controls. something like view layout [ h2 slider ] but that dosn't work.. there are hundreds of examples of how pretty the vid functions are, but I have failed to find much about using the results returned. |
Geomol 21-Apr-2009 [1825x3] | view layout [h: h2 "data shows here" slider [h/text: value show h]] |
A block after a style is being evaluated, when you operate the style. | |
The name of the variable holding the data for slider is called value. You have to look at docs to figure that out: http://www.rebol.com/docs/easy-vid.html Or you can look into the styles yourself, like: >> layout [s: slider] >> ? s | |
mhinson 21-Apr-2009 [1828] | Thanks Geomol, the docs dont seem to explain all the functions of the returned object. Is this detail recorded anywhere please? The object for slider is value, but value seems to be an object with lots of data & functions in it, how does it return the position I cant see how that is to be expected. |
Geomol 21-Apr-2009 [1829x3] | value comes from the function do-face. Try: >> source do-face |
Well, it might confuse to talk about do-face. :-) When you create a face (style) with an action block, it's set in the face. You can see it like this: >> layout [s: slider [print "hm"]] >> probe get in s 'action func [face value][print "hm"] That function is called, when you operate the style (face). Makes sense? | |
Now I both mention face and style. Styles are used to create faces. I guess, the GUI docs are not too clear in all of this. | |
Henrik 21-Apr-2009 [1832] | The value that s contains is the face object. This is not what you need to read out the value. Use GET-FACE s for that. |
Geomol 21-Apr-2009 [1833] | mhinson, you can get a more detailed documentation of the face object here: http://www.rebol.com/docs/view-system.html It document the view system, which you can see as being below VID. |
Henrik 21-Apr-2009 [1834] | LAYOUT is the VID dialect, which is REBOL's layout engine. When giving it a block of words, it produces a tree of objects, that each are a face. Each face contains sizes, offsets, colors, texts, event handlers and actions to perform when clicking on the face. |
older newer | first last |