I generally use NEdit and have a file that give highlighting for the common Fortran language.
I tried to add in some of the missing keywords like DEALLOCATE, CONTIGUOUS, etc and ailed miserably. I was using example from here: https://groups.google.com/forum/#!topic/comp.lang.fortran/D8JtR7m53z4
Does anyone have any good links for updated version of NEdit for F90+?
The highlights were putting in the Fortran90 before the Fortran around line 308. Still having issues with !?OMP but working well enough, and I use CAPS for Fortran Intrinsics and CamelCase for most Variables, Subroutines and Functions...
! Preferences file for NEdit
!
! This file is overwritten by the "Save Defaults..." command in NEdit
! and serves only the interactively settable options presented in the NEdit
! "Preferences" menu. To modify other options, such as key bindings, use
! the .Xdefaults file in your home directory (or the X resource
! specification method appropriate to your system). The contents of this
! file can be moved into an X resource file, but since resources in this file
! override their corresponding X resources, either this file should be
! deleted or individual resource lines in the file should be deleted for the
! moved lines to take effect.
nedit.fileVersion: 5.5
nedit.shellCommands: \
spell:Alt+B:s:ED:\n\
(cat;echo "") | spell\n\
wc::w:ED:\n\
wc | awk '{print $1 " lines, " $2 " words, " $3 " characters"}'\n\
sort::o:EX:\n\
sort\n\
number lines::n:AW:\n\
nl -ba\n\
make:Alt+Z:m:W:\n\
make\n\
expand::p:EX:\n\
expand\n\
unexpand::u:EX:\n\
unexpand\n
nedit.macroCommands: \
Complete Word:Alt+D::: {\n\
# Tuning parameters\n\
ScanDistance = 200\n\
\n\
# Search back to a word boundary to find the word to complete\n\
startScan = max(0, $cursor - ScanDistance)\n\
endScan = min($text_length, $cursor + ScanDistance)\n\
scanString = get_range(startScan, endScan)\n\
keyEnd = $cursor-startScan\n\
keyStart = search_string(scanString, "<", keyEnd, "backward", "regex")\n\
if (keyStart == -1)\n\
return\n\
keyString = "<" substring(scanString, keyStart, keyEnd)\n\
\n\
# search both forward and backward from the cursor position. Note that\n\
# using a regex search can lead to incorrect results if any of the special\n\
# regex characters is encountered, which is not considered a delimiter\n\
backwardSearchResult = search_string(scanString, keyString, keyStart-1, \\\n\
"backward", "regex")\n\
forwardSearchResult = search_string(scanString, keyString, keyEnd, "regex")\n\
if (backwardSearchResult == -1 && forwardSearchResult == -1) {\n\
beep()\n\
return\n\
}\n\
\n\
# if only one direction matched, use that, otherwise use the nearest\n\
if (backwardSearchResult == -1)\n\
matchStart = forwardSearchResult\n\
else if (forwardSearchResult == -1)\n\
matchStart = backwardSearchResult\n\
else {\n\
if (keyStart - backwardSearchResult <= forwardSearchResult - keyEnd)\n\
matchStart = backwardSearchResult\n\
else\n\
matchStart = forwardSearchResult\n\
}\n\
\n\
# find the complete word\n\
matchEnd = search_string(scanString, ">", matchStart, "regex")\n\
completedWord = substring(scanString, matchStart, matchEnd)\n\
\n\
# replace it in the window\n\
replace_range(startScan + keyStart, $cursor, completedWord)\n\
}\n\
Fill Sel. w/Char:::R: {\n\
if ($selection_start == -1) {\n\
beep()\n\
return\n\
}\n\
\n\
# Ask the user what character to fill with\n\
fillChar = string_dialog("Fill selection with what character?", "OK", "Cancel")\n\
if ($string_dialog_button == 2 || $string_dialog_button == 0)\n\
return\n\
\n\
# Count the number of lines in the selection\n\
nLines = 0\n\
for (i=$selection_start; i<$selection_end; i++)\n\
if (get_character(i) == "\\n")\n\
nLines++\n\
\n\
# Create the fill text\n\
rectangular = $selection_left != -1\n\
line = ""\n\
fillText = ""\n\
if (rectangular) {\n\
for (i=0; i<$selection_right-$selection_left; i++)\n\
line = line fillChar\n\
for (i=0; i<nLines; i++)\n\
fillText = fillText line "\\n"\n\
fillText = fillText line\n\
} else {\n\
if (nLines == 0) {\n\
for (i=$selection_start; i<$selection_end; i++)\n\
fillText = fillText fillChar\n\
} else {\n\
startIndent = 0\n\
for (i=$selection_start-1; i>=0 && get_character(i)!="\\n"; i--)\n\
startIndent++\n\
for (i=0; i<$wrap_margin-startIndent; i++)\n\
fillText = fillText fillChar\n\
fillText = fillText "\\n"\n\
for (i=0; i<$wrap_margin; i++)\n\
line = line fillChar\n\
for (i=0; i<nLines-1; i++)\n\
fillText = fillText line "\\n"\n\
for (i=$selection_end-1; i>=$selection_start && get_character(i)!="\\n"; \\\n\
i--)\n\
fillText = fillText fillChar\n\
}\n\
}\n\
\n\
# Replace the selection with the fill text\n\
replace_selection(fillText)\n\
}\n\
Quote Mail Reply:::: {\n\
if ($selection_start == -1)\n\
replace_all("^.*$", "\\\\> &", "regex")\n\
else\n\
replace_in_selection("^.*$", "\\\\> &", "regex")\n\
}\n\
Unquote Mail Reply:::: {\n\
if ($selection_start == -1)\n\
replace_all("(^\\\\> )(.*)$", "\\\\2", "regex")\n\
else\n\
replace_in_selection("(^\\\\> )(.*)$", "\\\\2", "regex")\n\
}\n\
Comments>/* Comment */#C#C++#Java#CSS#JavaScript#Lex:::R: {\n\
selStart = $selection_start\n\
selEnd = $selection_end\n\
replace_range(selStart, selEnd, "/* " get_selection() " */")\n\
select(selStart, selEnd + 6)\n\
}\n\
Comments>/* Uncomment */#C#C++#Java#CSS#JavaScript#Lex:::R: {\n\
sel = get_selection()\n\
selStart = $selection_start\n\
selEnd = $selection_end\n\
commentStart = search_string(sel, "/*", 0)\n\
if (substring(sel, commentStart + 2, commentStart + 3) == " ")\n\
keepStart = commentStart + 3\n\
else\n\
keepStart = commentStart + 2\n\
keepEnd = search_string(sel, "*/", length(sel), "backward")\n\
commentEnd = keepEnd + 2\n\
if (substring(sel, keepEnd - 1, keepEnd) == " ")\n\
keepEnd = keepEnd - 1\n\
replace_range(selStart + commentStart, selStart + commentEnd, \\\n\
substring(sel, keepStart, keepEnd))\n\
select(selStart, selEnd - (keepStart-commentStart) - \\\n\
(commentEnd - keepEnd))\n\
}\n\
Comments>// Comment#C#C++#Java#JavaScript:::R: {\n\
replace_in_selection("^.*$", "// &", "regex")\n\
}\n\
Comments>// Uncomment#C#C++#Java#JavaScript:::R: {\n\
replace_in_selection("(^[ \\\\t]*// ?)(.*)$", "\\\\2", "regex")\n\
}\n\
Comments># Comment#Perl#Sh Ksh Bash#NEdit Macro#Makefile#Awk#Csh#Python#Tcl:::R: {\n\
replace_in_selection("^.*$", "#&", "regex")\n\
}\n\
Comments># Uncomment#Perl#Sh Ksh Bash#NEdit Macro#Makefile#Awk#Csh#Python#Tcl:::R: {\n\
replace_in_selection("(^[ \\\\t]*#)(.*)$", "\\\\2", "regex")\n\
}\n\
Comments>-- Comment#SQL:::R: {\n\
replace_in_selection("^.*$", "--&", "regex")\n\
}\n\
Comments>-- Uncomment#SQL:::R: {\n\
replace_in_selection("(^[ \\\\t]*--)(.*)$", "\\\\2", "regex")\n\
}\n\
Comments>! Comment#X Resources:::R: {\n\
replace_in_selection("^.*$", "!&", "regex")\n\
}\n\
Comments>! Uncomment#X Resources:::R: {\n\
replace_in_selection("(^[ \\\\t]*!)(.*)$", "\\\\2", "regex")\n\
}\n\
Comments>% Comment#LaTeX:::R: {\n\
replace_in_selection("^.*$", "%&", "regex")\n\
}\n\
Comments>% Uncomment#LaTeX:::R: {\n\
replace_in_selection("(^[ \\\\t]*%)(.*)$", "\\\\2", "regex")\n\
}\n\
Comments>Bar Comment#C:::R: {\n\
if ($selection_left != -1) {\n\
dialog("Selection must not be rectangular")\n\
return\n\
}\n\
start = $selection_start\n\
end = $selection_end-1\n\
origText = get_range($selection_start, $selection_end-1)\n\
newText = "/*\\n" replace_in_string(get_range(start, end), \\\n\
"^", " * ", "regex") "\\n */\\n"\n\
replace_selection(newText)\n\
select(start, start + length(newText))\n\
}\n\
Comments>Bar Uncomment#C:::R: {\n\
selStart = $selection_start\n\
selEnd = $selection_end\n\
newText = get_range(selStart+3, selEnd-4)\n\
newText = replace_in_string(newText, "^ \\\\* ", "", "regex")\n\
replace_range(selStart, selEnd, newText)\n\
select(selStart, selStart + length(newText))\n\
}\n\
Make C Prototypes#C#C++:::: {\n\
if ($selection_start == -1) {\n\
start = 0\n\
end = $text_length\n\
} else {\n\
start = $selection_start\n\
end = $selection_end\n\
}\n\
string = get_range(start, end)\n\
nDefs = 0\n\
searchPos = 0\n\
prototypes = ""\n\
staticPrototypes = ""\n\
for (;;) {\n\
headerStart = search_string(string, \\\n\
"^[a-zA-Z]([^;#\\"'{}=><!/]|\\n)*\\\\)[ \\t]*\\n?[ \\t]*\\\\{", \\\n\
searchPos, "regex")\n\
if (headerStart == -1)\n\
break\n\
headerEnd = search_string(string, ")", $search_end,"backward") + 1\n\
prototype = substring(string, headerStart, headerEnd) ";\\n"\n\
if (substring(string, headerStart, headerStart+6) == "static")\n\
staticPrototypes = staticPrototypes prototype\n\
else\n\
prototypes = prototypes prototype\n\
searchPos = headerEnd\n\
nDefs++\n\
}\n\
if (nDefs == 0) {\n\
dialog("No function declarations found")\n\
return\n\
}\n\
new()\n\
focus_window("last")\n\
replace_range(0, 0, prototypes staticPrototypes)\n\
}\n
nedit.bgMenuCommands: \
Undo:::: {\n\
undo()\n\
}\n\
Redo:::: {\n\
redo()\n\
}\n\
Cut:::R: {\n\
cut_clipboard()\n\
}\n\
Copy:::R: {\n\
copy_clipboard()\n\
}\n\
Paste:::: {\n\
paste_clipboard()\n\
}\n
nedit.highlightPatterns: Ada:Default\n\
Awk:Default\n\
C++:Default\n\
C:Default\n\
CSS:Default\n\
Csh:Default\n\
Fortran:Default\n\
Fortran90:1:30{\n\
Continuation:"&":::Flag::\n\
String:"'":"'":"\\n([^ \\t]| [^ \\t]| [^ \\t]| [^ \\t]| [^ \\t]| [ \\t0]| *\\t[^1-9])":String::\n\
Keywords:"<(LT|GT|EQ|AND|OR|ACCEPT|[Aa]ccept|ASSIGN|[Aa]ssign|AUTOMATIC|[Aa]utomatic|BACKSPACE|[Bb]ackspace|BLOCK|[Bb]lock|CALL|[Cc]all|CLOSE|[Cc]lose|COMMON|[Cc]ommon|CONTINUE|[Cc]ontinue|DATA|[Dd]ata|DECODE|[Dd]ecode|DELETE|[Dd]elete|DIMENSION|[Dd]imension|DO|[Dd]o|ELSE|[Ee]lse|ELSEIF|[Ee]lseif|ENCODE|[Ee]ncode|ENDFILE|[Ee]nd[Ff]ile|ENDFILE|[Ee]ndfile|END|[Ee]nd|ENDIF|[Ee]ndif|ENTRY|[Ee]ntry|EQUIVALENCE|[Ee]quivalence|EXIT|[Ee]xit|EXTERNAL|[Ee]xternal|FORMAT|[Ff]ormat|FUNCTION|[Ff]unction|GOTO|[Gg]oto|IF|[Ii]f|IMPLICIT|[Ii]mplicit|INCLUDE|[Ii]nclude|INQUIRE|[Ii]nquire|INTRINSIC|[Ii]ntrinsic|LOGICAL|[Ll]ogical|MAP|[Mm]ap|NONE|[Nn]one|ON|[Oo]n|OPEN|[Oo]pen|PARAMETER|[Pp]arameter|PAUSE|[Pp]ause|POINTER|[Pp]ointer|PRINT|[Pp]rint|PROGRAM|[Pp]rogram|READ|[Rr]ead|RECORD|[Rr]ecord|RETURN|[Rr]eturn|REWIND|[Rr]ewind|SAVE|[Ss]ave|STATIC|[Ss]tatic|STOP|[Ss]top|STRUCTURE|[Ss]tructure|SUBROUTINE|[Ss]ubroutine|SYSTEM|[Ss]ystem|THEN|[Tt]hen|TO|[Tt]o|TYPE|[Tt]ype|UNION|[Uu]nion|MAP|UNLOCK|[Uu]nlock|VIRTUAL|[Vv]irtual|VOLATILE|[Vv]olatile|WHILE|[Ww]hile|WRITE|[Ww]rite)>":::Keyword::D\n\
Data Types:"<(BYTE|[Bb]yte|CHARACTER|[Cc]haracter|COMPLEX|[Cc]omplex|DOUBLE COMPLEX|[Dd]ouble *[Cc]omplex|DOUBLE *PRECISION|[Dd]ouble [Pp]recision|DOUBLE|[Dd]ouble|INTEGER|[Ii]nteger|REAL|[Rr]eal)(\\*[0-9]+)?>":::Keyword::D\n\
F90 Keywords:"<('!'DIR'$'|DIR|OMP|DEC|EQV|NEQV|KIND|SIMD|PARALLEL OFF|PARALLEL ON|ALLOCATABLE|[Aa]llocatable|ALLOCATE|[Aa]llocate|CASE|[Cc]ase|CASE|[Cc]ase|CONTAINS|CONTIGUOUS|[Cc]ontiguous|[Cc]ontains|CYCLE|[Cc]ycle|DEALLOCATE|[Dd]eallocate|ELSEWHERE|[Ee]lsewhere|ENDWHERE|[Ee]ndwhere|INTENT|[Ii]ntent|INTERFACE|[Ii]nterface|MODULE|[Mm]odule|NAMELIST|[Nn]amelist|OPTIONAL|[Oo]ptional|PRIVATE|[Pp]rivate|PROCEDURE|[Pp]rocedure|PUBLIC|[Pp]ublic|REWRITE|[Rr]ewrite|SELECT|[Ss]elect|USE|[Uu]se|WHERE|[Ww]here)>":::Keyword::D\n\
Numeric const:"<[0-9]+(\\.[0-9]*)?([DEde][-+]?[0-9]*)?|\\.[0-9]+([DEde][-+]?[0-9]*)?>":::Numeric Const::D\n\
Comment:"! ":"$"::Comment::\n\
}\n\
Java:Default\n\
JavaScript:Default\n\
LaTeX:Default\n\
Lex:Default\n\
Makefile:Default\n\
Matlab:Default\n\
NEdit Macro:Default\n\
Pascal:Default\n\
Perl:Default\n\
PostScript:Default\n\
Python:Default\n\
Regex:Default\n\
SGML HTML:Default\n\
SQL:Default\n\
Sh Ksh Bash:Default\n\
Tcl:Default\n\
VHDL:Default\n\
Verilog:Default\n\
XML:Default\n\
X Resources:Default\n\
Yacc:Default
nedit.languageModes: Ada:.ada .ad .ads .adb .a:::::::\n\
Awk:.awk:::::::\n\
C++:.cc .hh .C .H .i .cxx .hxx .cpp .c++::::::".,/\\`'!|##%^&*()-=+{}[]"":;<>?~":\n\
C:.c .h::::::".,/\\`'!|##%^&*()-=+{}[]"":;<>?~":\n\
CSS:css::Auto:None:::".,/\\`'!|##%^&*()=+{}[]"":;<>?~":\n\
Csh:.csh .cshrc .login .logout:"^[ \\t]*#[ \\t]*![ \\t]*/bin/csh"::::::\n\
Fortran90:.f90 .f03 .f08 .F90 .F03 .F08:::::::\n\
Fortran:.f .f77 .for :::::::\n\
Java:.java:::::::\n\
JavaScript:.js:::::::\n\
LaTeX:.tex .sty .cls .ltx .ins:::::::\n\
Lex:.lex:::::::\n\
Makefile:Makefile makefile .gmk:::None:8:8::\n\
Matlab:.m .oct .sci:::::::\n\
NEdit Macro:.nm .neditmacro:::::::\n\
Pascal:.pas .p .int:::::::\n\
Perl:.pl .pm .p5 .PL:"^[ \\t]*#[ \\t]*!.*perl":Auto:None:::".,/\\\\`'!$##%^&*()-=+{}[]"":;<>?~|":\n\
PostScript:.ps .eps .epsf .epsi:"^%!":::::"/%(){}[]<>":\n\
Python:.py:"^#!.*python":Auto:None:::"!""#$%&'()*+,-./:;<=>?#[\\\\]^`{|}~":\n\
Regex:.reg .regex:"\\(\\?[:#=!iInN].+\\)":None:Continuous::::\n\
SGML HTML:.sgml .sgm .html .htm:"\\<[Hh][Tt][Mm][Ll]\\>"::::::\n\
SQL:.sql:::::::\n\
Sh Ksh Bash:.sh .bash .ksh .profile .bashrc .bash_logout .bash_login .bash_profile:"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(bash|ksh|sh|zsh)"::::::\n\
Tcl:.tcl .tk .itcl .itk::Smart:None::::\n\
VHDL:.vhd .vhdl .vdl:::::::\n\
Verilog:.v:::::::\n\
XML:.xml .xsl .dtd:"\\<(?i\\?xml|!doctype)"::None:::"<>/=""'()+*?|":\n\
X Resources:.Xresources .Xdefaults .nedit:"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults"::::::\n\
Yacc:.y::::::".,/\\`'!|##%^&*()-=+{}[]"":;<>?~":
nedit.styles: Plain:black:Plain\n\
Comment:gray20:Italic\n\
Keyword:black:Bold\n\
Storage Type:brown:Bold\n\
Storage Type1:saddle brown:Bold\n\
String:darkGreen:Plain\n\
String1:SeaGreen:Plain\n\
String2:darkGreen:Bold\n\
Preprocessor:RoyalBlue4:Plain\n\
Preprocessor1:blue:Plain\n\
Character Const:darkGreen:Plain\n\
Numeric Const:darkGreen:Plain\n\
Identifier:brown:Plain\n\
Identifier1:RoyalBlue4:Plain\n\
Identifier2:SteelBlue:Plain\n\
Subroutine:brown:Plain\n\
Subroutine1:chocolate:Plain\n\
Ada Attributes:plum:Bold\n\
Label:red:Italic\n\
Flag:red:Bold\n\
Text Comment:SteelBlue4:Italic\n\
Text Key:VioletRed4:Bold\n\
Text Key1:VioletRed4:Plain\n\
Text Arg:RoyalBlue4:Bold\n\
Text Arg1:SteelBlue4:Bold\n\
Text Arg2:RoyalBlue4:Plain\n\
Text Escape:gray30:Bold\n\
LaTeX Math:darkGreen:Plain\n\
Pointer:#660000:Bold\n\
Regex:#009944:Bold\n\
Warning:brown2:Italic
nedit.smartIndentInit: C:Default\n\
C++:Default\n\
Python:Default\n\
Matlab:Default
nedit.smartIndentInitCommon: Default
nedit.autoWrap: Newline
nedit.wrapMargin: 0
nedit.autoIndent: Auto
nedit.autoSave: True
nedit.openInTab: True
nedit.saveOldVersion: False
nedit.showMatching: Delimiter
nedit.matchSyntaxBased: True
nedit.highlightSyntax: True
nedit.backlightChars: False
nedit.searchDialogs: False
nedit.beepOnSearchWrap: False
nedit.retainSearchDialogs: False
nedit.searchWraps: True
nedit.stickyCaseSenseButton: True
nedit.repositionDialogs: True
nedit.autoScroll: False
nedit.appendLF: True
nedit.sortOpenPrevMenu: True
nedit.statisticsLine: False
nedit.iSearchLine: False
nedit.sortTabs: False
nedit.tabBar: True
nedit.tabBarHideOne: True
nedit.toolTips: True
nedit.globalTabNavigate: False
nedit.lineNumbers: False
nedit.pathInWindowsMenu: True
nedit.warnFileMods: True
nedit.warnRealFileMods: True
nedit.warnExit: True
nedit.searchMethod: Literal
nedit.textRows: 24
nedit.textCols: 80
nedit.tabDistance: 8
nedit.emulateTabs: 0
nedit.insertTabs: True
nedit.textFont: -*-courier-medium-r-normal--*-120-*-*-*-iso8859-1
nedit.boldHighlightFont: -*-courier-bold-r-normal--*-120-*-*-*-iso8859-1
nedit.italicHighlightFont: -*-courier-medium-o-normal--*-120-*-*-*-iso8859-1
nedit.boldItalicHighlightFont: -*-courier-bold-o-normal--*-120-*-*-*-iso8859-1
nedit.textFgColor: black
nedit.textBgColor: rgb:e5/e5/e5
nedit.selectFgColor: black
nedit.selectBgColor: rgb:cc/cc/cc
nedit.hiliteFgColor: white
nedit.hiliteBgColor: red
nedit.lineNoFgColor: black
nedit.cursorFgColor: black
nedit.smartTags: True
nedit.prefFileRead: True
nedit.titleFormat: {%c} [%s] %f (%S) - %d
So it needs some more work for lower case and CamelCase, but it is working well enough.
Related
I'd like to execute for~loop using the \R\ delimiter.
DECLARE
v_idx NUMBER := 1;
v_text VARCHAR2(1000);
v_pattern VARCHAR2(32);
BEGIN
v_text := 'GR105^INF^191097-1^CT^test string r01\R\GR109^INF^191097-2^CR^test string r02 (1234)';
v_pattern := '\\R\\';
FOR repeat IN (SELECT trim(REGEXP_SUBSTR(v_text, v_pattern, 1, LEVEL)) item
FROM dual
CONNECT BY LEVEL <= REGEXP_COUNT(v_text, v_pattern))
LOOP
dbms_output.PUT_LINE('--------------- ' || v_idx || ' ---------------');
dbms_output.PUT_LINE('v_a = ' || trim(REGEXP_SUBSTR(repeat.item, '[^^]+', 1, 1)));
dbms_output.PUT_LINE('v_b = ' || trim(REGEXP_SUBSTR(repeat.item, '[^^]+', 1, 2)));
dbms_output.PUT_LINE('v_c = ' || trim(REGEXP_SUBSTR(repeat.item, '[^^]+', 1, 3)));
dbms_output.PUT_LINE('v_d = ' || trim(REGEXP_SUBSTR(repeat.item, '[^^]+', 1, 4)));
dbms_output.PUT_LINE('v_e = ' || trim(REGEXP_SUBSTR(repeat.item, '[^^]+', 1, 5)));
v_idx := v_idx + 1;
END LOOP;
END;
It works fine with '~' separator and '[^~]+' pattern.
But I don't know how to use '\R\'
You are only matching the delimiter \R\ and not the preceding sub-string. To match the preceding sub-string you can match (.*?)(\\R\\|$) and extract the contents of the first capturing group:
DECLARE
v_idx NUMBER := 1;
v_text VARCHAR2(1000);
v_pattern VARCHAR2(32);
BEGIN
v_text := 'GR105^INF^191097-1^CT^test string r01\R\GR109^INF^191097-2^CR^test string r02 (1234)';
v_pattern := '(.*?)(\\R\\|$)';
FOR repeat IN (SELECT trim(REGEXP_SUBSTR(v_text, v_pattern, 1, LEVEL, NULL, 1)) item
FROM dual
CONNECT BY LEVEL < REGEXP_COUNT(v_text, v_pattern))
LOOP
dbms_output.PUT_LINE('--------------- ' || v_idx || ' ---------------');
dbms_output.PUT_LINE('v_a = ' || trim(REGEXP_SUBSTR(repeat.item, '[^^]+', 1, 1)));
dbms_output.PUT_LINE('v_b = ' || trim(REGEXP_SUBSTR(repeat.item, '[^^]+', 1, 2)));
dbms_output.PUT_LINE('v_c = ' || trim(REGEXP_SUBSTR(repeat.item, '[^^]+', 1, 3)));
dbms_output.PUT_LINE('v_d = ' || trim(REGEXP_SUBSTR(repeat.item, '[^^]+', 1, 4)));
dbms_output.PUT_LINE('v_e = ' || trim(REGEXP_SUBSTR(repeat.item, '[^^]+', 1, 5)));
v_idx := v_idx + 1;
END LOOP;
END;
/
Note: LEVEL <= REGEXP_COUNT(v_text, v_pattern) needs to change to LEVEL < REGEXP_COUNT(v_text, v_pattern) as there will be a final zero-width match from the pattern (on .*?$) that needs to be ignored.
Which outputs:
--------------- 1 ---------------
v_a = GR105
v_b = INF
v_c = 191097-1
v_d = CT
v_e = test string r01
--------------- 2 ---------------
v_a = GR109
v_b = INF
v_c = 191097-2
v_d = CR
v_e = test string r02 (1234)
fiddle
I'm trying to separate addresses from 1 Cell to others. I match the city from a big array containing all Belgian cities. At the moment it works fine, except for this kind of exception:
In Belgium, we have a city called 'On'. This is a word you can find in street names too. Since I cannot know if the user will enter the city followed by the street or the street followed by the city, I have to distinct one from the other (I also cannot be sure that caps will be used or not).
The distinction is that 'on' in a street will almost definitively have an alphabetical letter stuck to it, either at the beginning or the end.
Example:
'Onderstraat',
'Donderstraat',
'Avenue du Bon'
I've tried this:
objRegExp.Pattern = "[^a-zA-ZàáâäÀÁÂÄèéêëÈÉÊËôöÔÖùúûüÙÚÛÜïÏçÇ]" & LCase(vaCitiesA(i)) & "[^a-zA-ZàáâäÀÁÂÄèéêëÈÉÊËôöÔÖùúûüÙÚÛÜïÏçÇ]"
But when they put the city at the end, then it doesn't match because there is NOTHING after the city (Schaarbeek in the example below)
example: 'blv Albert II 121a boîte 1, 1030 Schaarbeek'
What I would like is in the above, it will find Schaarbeek, but with Onderstraat, Donderstraat or av du Bon it shouldn't get a match with city 'On'
OP's working code removed from question and posted in answer form:
Dim vaCitiesA As Variant
Dim xSelection As Range
Dim xCity As String
Dim rest As String
vaCitiesA = Array("Hody", "Hour", "Houx", "HOVE", "Hyon", "Impe", "Izel", "Jeuk", "Kain", "Laar", "Lauw", "LEDE", "Leke", "LENS", "Leut", "LIER", "LINT", "Mark", "Mazy", _
"Mean", "Meer", "Mere", "Meux", "Moen", "Moha", "MONS", "Mont", "Mont", "Muno", "NATO", "NIEL", "Nimy", "OHEY", "Oizy", "OLEN", "OLNE", "Omal", "Onoz", _
"Orcq", "Oret", "Paal", "PECQ", "PEER", "Perk", "Redu", "Reet", "Roly", "Roux", "RTBF", "Seny", "Soye", "Suxy", "Thon", "Thys", "Velm", "VISE", "Vivy", _
"Waha", "Ways", "Werm", "ZELE", "ANS", "ATH", "Aye", "Bra", "Eke", "Ere", "Goe", "HAM", "HUY", "Lot", "Mal", "MOL", "Ogy", "Pry", "Roy", _
"Scy", "SOC", "Soy", "SPA", "Spy", "VRT", "VTM", "AS", "Lo", "My", "On")
Set xSelection = Application.Selection
For Each Rng In xSelection
Dim allMatches As Object
Dim objRegExp As Object
'Initializing an Instance
Set objRegExp = CreateObject("VBScript.RegExp")
'Setting the Properties
With objRegExp
.Global = True
.IgnoreCase = True
End With
xCity = ""
rest = Rng.Value
'a
rest = Replace(rest, "à", "a")
rest = Replace(rest, "â", "a")
rest = Replace(rest, "á", "a")
rest = Replace(rest, "À", "A")
rest = Replace(rest, "Â", "A")
rest = Replace(rest, "Á", "A")
'e
rest = Replace(rest, "ë", "e")
rest = Replace(rest, "é", "e")
rest = Replace(rest, "è", "e")
rest = Replace(rest, "ê", "e")
rest = Replace(rest, "Ë", "E")
rest = Replace(rest, "É", "E")
rest = Replace(rest, "È", "E")
rest = Replace(rest, "Ê", "E")
'o
rest = Replace(rest, "ö", "o")
rest = Replace(rest, "ô", "o")
rest = Replace(rest, "Ö", "O")
rest = Replace(rest, "Ô", "O")
'u
rest = Replace(rest, "ü", "u")
rest = Replace(rest, "û", "u")
rest = Replace(rest, "ù", "u")
rest = Replace(rest, "ú", "u")
rest = Replace(rest, "Ü", "U")
rest = Replace(rest, "Û", "U")
rest = Replace(rest, "Ù", "U")
rest = Replace(rest, "Ú", "U")
'i
rest = Replace(rest, "ï", "i")
rest = Replace(rest, "Ï", "I")
'c
rest = Replace(rest, "ç", "c")
rest = Replace(rest, "Ç", "C")
'special
rest = Replace(rest, "'", "")
rest = Replace(rest, "-", " ")
Text = LCase(rest)
For i = LBound(vaCitiesA) To UBound(vaCitiesA)
'''''''''''''''''''''''''''''''''''''
objRegExp.Pattern = "(^|[^a-zA-ZàáâäÀÁÂÄèéêëÈÉÊËôöÔÖùúûüÙÚÛÜïÏçÇ])" & LCase(vaCitiesG(i)) & "(?![a-zA-ZàáâäÀÁÂÄèéêëÈÉÊËôöÔÖùúûüÙÚÛÜïÏçÇ])"
Set allMatches = objRegExp.Execute(Text)
If objRegExp.Test(Text) Then
xCity = vaCitiesA(i)
Exit For
End If
''''''''''''''''''''''''''''''''''''''''
Next i
If xCity <> "" Then
'for the moment, I choose last match, but could be problematic if there is a short city like 'ON' in front of the street
x = allMatches.Count - 1
lCityPos = allMatches(x).FirstIndex
rest = Replace(rest, Mid(rest, lCityPos + 1, Len(xCity) + 1), "", , 1)
End If
so I am writing a program to find specific lines in a dump from the uninstall registry, and then write those lines to a new text file. Here is the code.
fileName = "export.txt"
outputFileName = input("Enter the Output File Name")
inputFile = open(fileName, "r")
outputFile = open(outputFileName, "w")
displayName = ""
displayVersion = ""
publisher = ""
for line in inputFile:
if "DisplayName" in line:
lst = line.split("=")
displayName = lst[1][1:len(lst[1])-1]
if "DisplayVersion" in line:
lst = line.split("=")
displayVersion = lst[1][1:len(lst[1])-1]
if "Publisher" in line:
lst = line.split("=")
publisher = lst[1][1:len(lst[1])-1]
if displayName!= "" or displayVersion != "" or publisher != "":
outputFile.write(displayName + "\t" + displayVersion + "\t" +publisher + "\n")
displayName = ""
displayVersion = ""
publisher = ""
inputFile.close()
outputFile.close()
For some reason, the first three if statements are not being entered. Here is a snippet from the export.txt text file.
[HKEY_LOCAL_MACHINE\SoftWare\Microsoft\Windows\CurrentVersion\Uninstall\Matlab R2016b]
"DisplayName"="MATLAB R2016b"
"UninstallString"="C:\\Program Files\\MATLAB\\R2016b\\uninstall\\bin\\win64\\uninstall.exe C:\\Program Files\\MATLAB\\R2016b"
"DisplayIcon"="C:\\Program Files\\MATLAB\\R2016b\\bin\\win64\\matlab.ico"
"InstallLocation"="C:\\Program Files\\MATLAB\\R2016b"
"DisplayVersion"="9.1"
"URLInfoAbout"="www.mathworks.com"
"Publisher"="MathWorks"
"HelpLink"="www.mathworks.com/support"
"Comments"=" "
ê[HKEY_LOCAL_MACHINE\SoftWare\Microsoft\Windows\CurrentVersion\Uninstall\Matlab
R2016b]
“DisplayName””MATLAB R201 6b”
“UninstallString””C: \\Prograrn
Files\\MATLAB\\R2016b\\uninstall\\bin\\win64\\uninstall.exe C: \\Prograrn
Files\\frIATLAB\\R201 6b”
“Displaylcon””C:\\Prograrn Files\\MATLAB\\R2016b\\bin\\win64\\matlab. ico”
“InstallLocation””C: \\Prograrn Files\\MATLAB\\R201 6b”
“DisplayVersion””9. 1”
“URLlnfoAbout””www. mathworks. corn”
“Publisher”=”MathWorks”
“HelpLink””www. rnathworks. corn/support”
“Comments”” “
The logic of your last if statement is completely reversed. It should be or instead of and in order for your statement to work properly.
What about checking in a different way using find()?
if line.find("DisplayName") != -1:
do stuff.
I ran this fine, here's the code:
fileName = "export.txt"
outputFileName = input("Enter the Output File Name")
inputFile = open(fileName, "r")
outputFile = open(outputFileName, "w")
displayName = ""
displayVersion = ""
publisher = ""
for line in inputFile:
print line
if line.find("DisplayName") != -1:
lst = line.split("=")
displayName = lst[1][1:len(lst[1])-2]
if line.find("DisplayVersion") != -1:
print "here2"
lst = line.split("=")
displayVersion = lst[1][1:len(lst[1])-2]
if line.find("Publisher") != -1:
print "here3"
lst = line.split("=")
publisher = lst[1][1:len(lst[1])-2]
if displayName!= "" and displayVersion != "" and publisher != "":
print "Here4"
print displayName + "\t" + displayVersion + "\t" +publisher
outputFile.write(displayName + "\t" + displayVersion + "\t" +publisher)
displayName = ""
displayVersion = ""
publisher = ""
inputFile.close()
outputFile.close()
produces:
MATLAB R2016b 9.1 MathWorks
The output while running the script looks like this:
Enter the Output File Name"out.txt"
[HKEY_LOCAL_MACHINE\SoftWare\Microsoft\Windows\CurrentVersion\Uninstall\Matlab R2016b]
"DisplayName"="MATLAB R2016b"
"UninstallString"="C:\Program Files\MATLAB\R2016b\uninstall\bin\win64\uninstall.exe C:\Program Files\MATLAB\R2016b"
"DisplayIcon"="C:\Program Files\MATLAB\R2016b\bin\win64\matlab.ico"
"InstallLocation"="C:\Program Files\MATLAB\R2016b"
"DisplayVersion"="9.1"
here2
"URLInfoAbout"="www.mathworks.com"
"Publisher"="MathWorks"
here3
Here4
MATLAB R2016b 9.1 MathWorks
"HelpLink"="www.mathworks.com/support"
"Comments"=" "
I've had this function for almost two years now, and I can't seem to figure out why it's not working for colorizing. Here's the entire function, but you'll see the core parts that aren't working below.
function showscoreboard()
local function len(arg)
return string.len(arg)
end
local function tbuff(arg)
if len(arg) < 3 then
return arg.." "
else
return arg
end
end
local function sbuff(arg)
if len(arg) < 2 then
return " "..arg
else
return arg
end
end
local function cteam(t,s)
local status = s or nil
local forecolor = ""
if status == "p" then
forecolor = "yellow"
elseif status == "w" then
forecolor = "cyan"
else
forecolor = "limegreen"
end
return "<color fore="..forecolor..">"..t.."</color>"
end
local function bcolor(i)
local i = i or 0
if i%2 == 1 then
return "maroon"
else
return "navy"
end
end
local scorestring = ""
local allteams = {["ATL"]=0,["WAS"]=0,["MIA"]=0,["CLE"]=0,["OAK"]=0,["SD"]=0,["IND"]=0,["NYJ"]=0,["TEN"]=0,["SEA"]=0,["PHI"]=0,["DEN"]=0,["GB"]=0,["BUF"]=0,["TB"]=0,["PIT"]=0,["MIN"]=0,["HOU"]=0,["DET"]=0,["TB"]=0,["CAR"]=0,["CHI"]=0,["STL"]=0,["NYG"]=0,["ARI"]=0,["NO"]=0,["KC"]=0,["SF"]=0,["NE"]=0}
local byeweek = ""
for _,v in ipairs(nflscores.ss) do
allteams[v[5]] = 1
allteams[v[7]] = 1
end
for i,v in pairs(allteams) do
if v == 0 then
byeweek = byeweek .. "<color white>".. i .."</color>\r"
end
end
for i,v in ipairs(nflscores.ss) do
local hteam = v[7]
local ateam = v[5]
local qgame = v[3]
local hscre = v[8] or 0
local ascre = v[6] or 0
if v[4] then
qtime = "<color white>Time: "..v[4].."</color>"
else
qtime = ""
end
local gposs = v[9] or ""
if gposs ~= "" then
if gposs == hteam then
hteam = cteam(tbuff(hteam),"p")
ateam = cteam(tbuff(ateam))
else
ateam = cteam(tbuff(ateam),"p")
hteam = cteam(tbuff(hteam))
end
else
hteam = cteam(tbuff(hteam))
ateam = cteam(tbuff(ateam))
end
if qgame == "Final" or qgame == "final overtime" then
if hscre > ascre then
hteam = cteam(tbuff(hteam),"w")
ateam = cteam(tbuff(ateam))
elseif hscre < ascre then
ateam = cteam(tbuff(ateam),"w")
hteam = cteam(tbuff(hteam))
else
ateam = cteam(tbuff(ateam))
hteam = cteam(tbuff(hteam))
end
if qgame == "Final" then
qgame = "<color cyan>F</color>"
elseif qgame == "final overtime" then
qgame = "<color cyan>F/OT</color>"
end
elseif qgame == "Pregame" then
qgame = "<color cyan>Pre</color>"
elseif qgame == "Halftime" then
qgame = "<color white>"..qgame.."</color>"
else
qgame = "<color white>Q"..qgame.."</color>"
end
scorestring = scorestring .. "<color back="..bcolor(i) .. ">".. v[1] .. ": " .. ateam .. "<color white>: " .. sbuff(ascre) .. "</color> <color black>#</color> " .. hteam .. "<color white>: ".. sbuff(hscre) .."</color></color> " .. qgame .. " " .. qtime .. "\r"
end
return scorestring .. "<color white>Bye week:</color>\r"..byeweek
end
The part that isn't working properly is:
if hscre > ascre then
hteam = cteam(tbuff(hteam),"w")
ateam = cteam(tbuff(ateam))
elseif hscre < ascre then
ateam = cteam(tbuff(ateam),"w")
hteam = cteam(tbuff(hteam))
else
ateam = cteam(tbuff(ateam))
hteam = cteam(tbuff(hteam))
end
The function for cteam is:
local function cteam(t,s)
local status = s or nil
local forecolor = ""
if status == "p" then
forecolor = "yellow"
elseif status == "w" then
forecolor = "cyan"
else
forecolor = "limegreen"
end
return "<color fore="..forecolor..">"..t.."</color>"
end
Now, it colors the "p" status just fine. But when the status changes to "w", it fails, and for the life of me, I cannot figure out why. Am I missing something? Could this code be a lot cleaner?
Edit: I haven't found the issue to the problem, but apparently the "elseif status == "w" statement is completely bypassed. When the games are being played, the correct team in possession shows yellow. However, after the game is over, both teams are lime green, as if no score was higher than the other.
2nd Edit: The error listed in the first answer has been corrected. Still, it doesn't solve the issue. I'm still quite at a loss.
Nothing jumps out and I can't test here but here are some things to check:
You mention that cteam works correctly during the game, and that it's only once the game is over that cteam doesn't give the correct final result. So the logic of cteam is correct. The problem must be in the code that calls cteam: does cteam ever get called with s equals "w": this would never happen if hscre and ascre are always the same. Also there is a typo in the branch code that calls cteam:
if hscre > ascre then
hteam = cteam(tbuff(hteam),"w")
ateam = cteam(tbuff(ateam))
elseif hscre < ascre then
ateam = cteam(tbuff(ateam,"w")) -- ERR
hteam = cteam(tbuff(hteam))
else
ateam = cteam(tbuff(ateam))
hteam = cteam(tbuff(hteam))
end
The line that is tagged ERR should be:
ateam = cteam(tbuff(ateam),"w")
About cleaning up the code: post your question on StackOverflow's code review forum.
I need to parse an CSV file using AWK. A line in the CSV could look like this:
"hello, world?",1 thousand,"oneword",,,"last one"
Some important observations:
-field inside quoted string can contain commas and multiple words
-unquoted field can be multiple worlds
-field can be empty by just having two commas in a row
Any clues on writing a regex expression to split this line up properly?
Thanks!
As many have observed, CSV is a harder format than it first appears. There are many edge cases and ambiguities. As an example ambiguity, in your example, is ',,,' a field with a comma or two blank fields?
Perl, python, Java, etc are better equipped to deal with CSV because they have well tested libraries for the same. A regex will be more fragile.
With AWK, I have had some success with THIS AWK function. It works under AWK, gawk and nawk.
#!/usr/bin/awk -f
#**************************************************************************
#
# This file is in the public domain.
#
# For more information email LoranceStinson+csv#gmail.com.
# Or see http://lorance.freeshell.org/csv/
#
# Parse a CSV string into an array.
# The number of fields found is returned.
# In the event of an error a negative value is returned and csverr is set to
# the error. See below for the error values.
#
# Parameters:
# string = The string to parse.
# csv = The array to parse the fields into.
# sep = The field separator character. Normally ,
# quote = The string quote character. Normally "
# escape = The quote escape character. Normally "
# newline = Handle embedded newlines. Provide either a newline or the
# string to use in place of a newline. If left empty embedded
# newlines cause an error.
# trim = When true spaces around the separator are removed.
# This affects parsing. Without this a space between the
# separator and quote result in the quote being ignored.
#
# These variables are private:
# fields = The number of fields found thus far.
# pos = Where to pull a field from the string.
# strtrim = True when a string is found so we know to remove the quotes.
#
# Error conditions:
# -1 = Unable to read the next line.
# -2 = Missing end quote.
# -3 = Missing separator.
#
# Notes:
# The code assumes that every field is preceded by a separator, even the
# first field. This makes the logic much simpler, but also requires a
# separator be prepended to the string before parsing.
#**************************************************************************
function parse_csv(string,csv,sep,quote,escape,newline,trim, fields,pos,strtrim) {
# Make sure there is something to parse.
if (length(string) == 0) return 0;
string = sep string; # The code below assumes ,FIELD.
fields = 0; # The number of fields found thus far.
while (length(string) > 0) {
# Remove spaces after the separator if requested.
if (trim && substr(string, 2, 1) == " ") {
if (length(string) == 1) return fields;
string = substr(string, 2);
continue;
}
strtrim = 0; # Used to trim quotes off strings.
# Handle a quoted field.
if (substr(string, 2, 1) == quote) {
pos = 2;
do {
pos++
if (pos != length(string) &&
substr(string, pos, 1) == escape &&
(substr(string, pos + 1, 1) == quote ||
substr(string, pos + 1, 1) == escape)) {
# Remove escaped quote characters.
string = substr(string, 1, pos - 1) substr(string, pos + 1);
} else if (substr(string, pos, 1) == quote) {
# Found the end of the string.
strtrim = 1;
} else if (newline && pos >= length(string)) {
# Handle embedded newlines if requested.
if (getline == -1) {
csverr = "Unable to read the next line.";
return -1;
}
string = string newline $0;
}
} while (pos < length(string) && strtrim == 0)
if (strtrim == 0) {
csverr = "Missing end quote.";
return -2;
}
} else {
# Handle an empty field.
if (length(string) == 1 || substr(string, 2, 1) == sep) {
csv[fields] = "";
fields++;
if (length(string) == 1)
return fields;
string = substr(string, 2);
continue;
}
# Search for a separator.
pos = index(substr(string, 2), sep);
# If there is no separator the rest of the string is a field.
if (pos == 0) {
csv[fields] = substr(string, 2);
fields++;
return fields;
}
}
# Remove spaces after the separator if requested.
if (trim && pos != length(string) && substr(string, pos + strtrim, 1) == " ") {
trim = strtrim
# Count the number fo spaces found.
while (pos < length(string) && substr(string, pos + trim, 1) == " ") {
trim++
}
# Remove them from the string.
string = substr(string, 1, pos + strtrim - 1) substr(string, pos + trim);
# Adjust pos with the trimmed spaces if a quotes string was not found.
if (!strtrim) {
pos -= trim;
}
}
# Make sure we are at the end of the string or there is a separator.
if ((pos != length(string) && substr(string, pos + 1, 1) != sep)) {
csverr = "Missing separator.";
return -3;
}
# Gather the field.
csv[fields] = substr(string, 2 + strtrim, pos - (1 + strtrim * 2));
fields++;
# Remove the field from the string for the next pass.
string = substr(string, pos + 1);
}
return fields;
}
{
num_fields = parse_csv($0, csv, ",", "\"", "\"", "\\n", 1);
if (num_fields < 0) {
printf "ERROR: %s (%d) -> %s\n", csverr, num_fields, $0;
} else {
printf "%s -> \n", $0;
printf "%s fields\n", num_fields;
for (i = 0;i < num_fields;i++) {
printf "%s\n", csv[i];
}
printf "|\n";
}
}
Running it on your example data produces:
"hello, world?",1 thousand,"oneword",,,"last one" ->
6 fields
hello, world?
1 thousand
oneword
last one
|
An example Perl solution:
$ echo '"hello, world?",1 thousand,"oneword",,,"last one"' |
perl -lnE 'for(/(?:^|,)("(?:[^"]+|"")*"|[^,]*)/g) { s/"$//; s/""/"/g if (s/^"//);
say}'
Try this:
^(("(?:[^"]|"")*"|[^,]*)(,("(?:[^"]|"")*"|[^,]*))*)$
I haven't tested it with AWK though.