Here is a major new release, version 6.2, with lots of new features.Many of the the new features are designed to reduce the need for user supplied JScript, and/or to facilitate use of simpler regular expressions to solve a particular task. Performance is also improved.
I'll break the new features into numbered sections, based on common themes. I'll only provide a brief summary of each new feature, plus examples. See the documentation for the complete syntax and behavior.
1) Improved Help systemNew HISTORY topicPrints out the full release history of JREPL.BAT.
Check out the lines next to
2016-10-08 v6.0: for a summary of all the new features in this release.
Code: Select all
>jrepl /?history
2016-10-13 v6.2: Bug fix - /J, /JQ, /JMATCH, /JMATCHQ did not work with /P.
2016-10-08 v6.1: Bug fix - v6.0 broke /JBEG and /JLIB, all fixed.
2016-10-08 v6.0: Added /K - search and write matching lines.
Added /R - search and write non-matching lines.
Added /MATCH - search and write each match on a new line.
Added /P - Pre-filter regex before normal search/replace.
Added /PFLAG - set search flags for /P regex
Added /JQ and /JMATCHQ as Quick forms of /J and /JMATCH.
Augmented /INC and /EXC so can now specify lines by regex.
Changed behavior - /V now applies to /INC and /EXC.
Improved performance of /INC, /EXC, /T, /JBEGLN, /JENDLN.
Added HISTORY and UPDATE topics to the help system.
2016-09-27 v5.2: Bug fix - Search & Replace now ignore /V if /T FILE used.
Added a /T FILE example to the documentation.
2016-09-20 v5.1: Added the FILE alternative for the /T option.
2016-09-18 v5.0: Added the /U option for Unix line terminators of /n.
2016-08-04 v4.6: Fixed the /N documentation (reparired missing line)
2016-08-03 v4.5: Added /D option to specify delimiter for /N and /OFF.
2016-08-02 v4.4: Bug fix - /C count was wrong when last line did not end
with new line. This also affected /INC and /EXC.
2016-07-30 v4.3: Added rpad() function and improved lpad()
2016-06-24 v4.2: Improved the /?Options help.
2016-06-23 v4.1: Added /T option examples to the help.
Added ability to request help on a single option or topic.
2016-06-19 v4.0: Added the /INC and /EXC options.
2016-03-27 v3.8: Bug fix - Hide leaked global variables i, lib, libs, rtn2.
Bug fix - Work around %~f0 bug when command is quoted.
Bug fix - Use /OPTIONS instead of OPTIONS as a variable
name within the option parser so that it is unlikely to
collide with a user defined variable name.
2016-01-14 v3.7: Reworked error handling a bit.
Bug fix - \xnn and \unnnn could fail in a regex search
if result was a meta-character and /X option was used.
2015-07-15 v3.6: Added /?? option for paged help.
2015-06-12 v3.5: Bug fix for $n or $nn in replace string when /T is
used without /J or /JMATCH or /L
2015-01-22 v3.4: Bug fix - Use /TEST instead of TEST as a variable name
within the option parser so that it is unlikely to
collide with a user defined variable name.
2014-12-24 v3.3: Bug fix for when /JMATCH is combined with /M or /S
2014-12-09 v3.2: Bug fix for /T without /JMATCH - fixed dynamic repl func
Added GOTO at top for improved startup performance
2014-11-25 v3.1: Added /JLIB option
Exception handler reports when regex is bad
Fix /X bug with extended ASCII
2014-11-23 v3.0: Added /JBEGLN and /JENDLN options
Added skip, quit, and lpad() global variables/functions
Exception handler reports when error in user code
2014-11-21 v2.2: Bug fix for /T with /L option.
2014-11-20 v2.1: Bug fix for /T option when match is an empty string
2014-11-17 v2.0: Added /T (translate) and /C (count input lines) options
2014-11-14 v1.0: Initial release
Easily check if there is a new version availableOpens up the first post of this thread in your browser so you can easily check if there is a newer version available.
Code: Select all
>:: The following command will open up the first post of this thread in your browser
>jrepl /?update
2) Search only, without doing any replace (more like grep, or a glorified FINDSTR)My syntax has always required that the first two arguments are the Search and Replace strings. I didn't want to break any existing scripts that use JREPL, so I opted not to change the syntax. So the Replace argument is still required, but it is simply ignored. The easiest thing to do is pass an empty string using "".
events.txt (test file)
Code: Select all
Session 1 - The mysteries of magic
07:00 AM Event 1 - Abracadabra
08:00 AM Event 2 - Where did it go?
09:00 AM Event 3 - How could you know that?
Session 2 - You won't believe your eyes
10:00 AM Event 4 - Ouch, that's gotta hurt
11:00 AM Event 5 - The strongest man alive
12:00 PM Event 6 - How can she bend like that?
Session 3 - Don't say you weren't warned
01:00 PM Event 7 - I can't bear to look
02:00 PM Event 8 - Now that's gross
03:00 PM Event 9 - Hold your nose
/K Context
/K PreContext:PostContextKeep lines that contain at least one string that matches the Search. The Context is required. It determines how many non-mathching lines to display before and/or after each matching line.
Examples:
Code: Select all
>:: Write lines that begin with a capital letter
>jrepl "^[A-Z]" "" /k 0 /f events.txt
Session 1 - The mysteries of magic
Session 2 - You won't believe your eyes
Session 3 - Don't say you weren't warned
>:: Same as above, but include 1 non-matching line after each match
>jrepl "^[A-Z]" "" /k 0:1 /f events.txt
Session 1 - The mysteries of magic
07:00 AM Event 1 - Abracadabra
Session 2 - You won't believe your eyes
10:00 AM Event 4 - Ouch, that's gotta hurt
Session 3 - Don't say you weren't warned
01:00 PM Event 7 - I can't bear to look
>:: Same as above, but include 1 non-matching line before and after each match
>jrepl "^[A-Z]" "" /k 1 /f events.txt
Session 1 - The mysteries of magic
07:00 AM Event 1 - Abracadabra
09:00 AM Event 3 - How could you know that?
Session 2 - You won't believe your eyes
10:00 AM Event 4 - Ouch, that's gotta hurt
12:00 PM Event 6 - How can she bend like that?
Session 3 - Don't say you weren't warned
01:00 PM Event 7 - I can't bear to look
>:: You can easily draw your eyes to matching lines among context if you add the /OFF option.
>jrepl "^[A-Z]" "" /k 1 /off 1 /d " " /f events.txt
0 Session 1 - The mysteries of magic
07:00 AM Event 1 - Abracadabra
09:00 AM Event 3 - How could you know that?
0 Session 2 - You won't believe your eyes
10:00 AM Event 4 - Ouch, that's gotta hurt
12:00 PM Event 6 - How can she bend like that?
0 Session 3 - Don't say you weren't warned
01:00 PM Event 7 - I can't bear to look
/R Context
/R PreContext:PostContextReject lines that contain at least one string that matches the Search. In other words, print out lines that don't match. The Context feature is perhaps counter-intuitive for non-matching lines, but it works the same as for /K. A non-zero value will print out matching lines before and/or after each non-matching line.
Examples:
Code: Select all
>:: Reject lines that begin with a digit
>jrepl "^\d" "" /r 0 /f events.txt
Session 1 - The mysteries of magic
Session 2 - You won't believe your eyes
Session 3 - Don't say you weren't warned
>:: Same as above, but include 1 matching line after each non-match
>jrepl "^\d" "" /r 0:1 /f events.txt
Session 1 - The mysteries of magic
07:00 AM Event 1 - Abracadabra
Session 2 - You won't believe your eyes
10:00 AM Event 4 - Ouch, that's gotta hurt
Session 3 - Don't say you weren't warned
01:00 PM Event 7 - I can't bear to look
>:: Same as above, but include 1 matching line before and after each match
>:: Note that /OFF will not work with /R
>jrepl "^\d" "" /r 1 /f events.txt
Session 1 - The mysteries of magic
07:00 AM Event 1 - Abracadabra
09:00 AM Event 3 - How could you know that?
Session 2 - You won't believe your eyes
10:00 AM Event 4 - Ouch, that's gotta hurt
12:00 PM Event 6 - How can she bend like that?
Session 3 - Don't say you weren't warned
01:00 PM Event 7 - I can't bear to look
/MATCHWrite out each string that matches on a new line. Discard all other text.
Example:
Code: Select all
>:: List out all events, without time
>jrepl "Event.*" "" /match /f events.txt
Event 1 - Abracadabra
Event 2 - Where did it go?
Event 3 - How could you know that?
Event 4 - Ouch, that's gotta hurt
Event 5 - The strongest man alive
Event 6 - How can she bend like that?
Event 7 - I can't bear to look
Event 8 - Now that's gross
Event 9 - Hold your nose!
>:: Write each number and time on a new line, and show the location of each match
>jrepl "[\d:]+( [AP]M)?" "" /match /n 2 /off 2 /d . /f events.txt
01.08.1
02.00.07:00 AM
02.16.1
03.00.08:00 AM
03.16.2
04.00.09:00 AM
04.16.3
05.08.2:
06.00.10:00 AM
06.16.4
07.00.11:00 AM
07.16.5
08.00.12:00 PM
08.16.6
09.08.3:
10.00.01:00 PM
10.16.7
11.00.02:00 PM
11.16.8
12.00.03:00 PM
12.16.9
3) Limit searches (and replaces) to selected regions within the input textImproved /INC and /EXC options/INC and /EXC restrict searches to blocks of lines. They introduced in version 4.0, but blocks had to be identified by line numbers. Since this filtering is line based, it cannot be used with /S or /M options.
New features for version 6.0
- Specify lines and/or rangeBegin and/or rangeEnd by regular expressions
- Apply optional offset to any line position
- Specify rangeEnd by line offset from rangeBegin
Note - Because regular expressions frequently use quoted ^, which becomes ^^ when CALL is used, a method was needed to avoid putting ^ directly in the command line.
I opted to modify /V to make it also apply to /INC and /EXC. This new behavior has the potential to break an existing script.In the unlikely event that you already have a version 4 or 5 script that uses /V with /INC or /EXC, then you will have to modify your script to put the /INC or /EXC value in a variable.
Examples:
Code: Select all
>:: List all morning events
>jrepl "" "" /k 0 /inc "/ AM /" /f events.txt
07:00 AM Event 1 - Abracadabra
09:00 AM Event 3 - How could you know that?
10:00 AM Event 4 - Ouch, that's gotta hurt
>:: List the first event of each session, without displaying the session info
>jrepl "" "" /k 0 /inc "/^session/i+1" /f events.txt
07:00 AM Event 1 - Abracadabra
10:00 AM Event 4 - Ouch, that's gotta hurt
01:00 PM Event 7 - I can't bear to look
>:: List the itineary for the first session, only knowing that session lines begin with a letter
>jrepl "" "" /k 0 /inc "/^[a-z]/i/:/^[a-z]/i-1" /f events.txt
Session 1 - The mysteries of magic
07:00 AM Event 1 - Abracadabra
08:00 AM Event 2 - Where did it go?
09:00 AM Event 3 - How could you know that?
>:: List each session, plus its first event
>jrepl "" "" /k 0 /inc "/^[a-z]/i:+1" /f events.txt
Session 1 - The mysteries of magic
07:00 AM Event 1 - Abracadabra
Session 2 - You won't believe your eyes
10:00 AM Event 4 - Ouch, that's gotta hurt
Session 3 - Don't say you weren't warned
01:00 PM Event 7 - I can't bear to look
>:: Change the start time to the half hour for all events in Session 2
>jrepl "^(\d\d):\d\d" "$1:30" /inc "/^Session 2/:/^Session/" /f events.txt
Session 1 - The mysteries of magic
07:00 AM Event 1 - Abracadabra
08:00 AM Event 2 - Where did it go?
09:00 AM Event 3 - How could you know that?
Session 2 - You won't believe your eyes
10:30 AM Event 4 - Ouch, that's gotta hurt
11:30 AM Event 5 - The strongest man alive
12:30 PM Event 6 - How can she bend like that?
Session 3 - Don't say you weren't warned
01:00 PM Event 7 - I can't bear to look
02:00 PM Event 8 - Now that's gross
03:00 PM Event 9 - Hold your nose!
>:: Change the start time to the half hour for all events except for those in Session 2
>jrepl "^(\d\d):\d\d" "$1:30" /exc "/^Session 2/:/^Session/" /f events.txt
Session 1 - The mysteries of magic
07:30 AM Event 1 - Abracadabra
08:30 AM Event 2 - Where did it go?
09:30 AM Event 3 - How could you know that?
Session 2 - You won't believe your eyes
10:00 AM Event 4 - Ouch, that's gotta hurt
11:00 AM Event 5 - The strongest man alive
12:00 PM Event 6 - How can she bend like that?
Session 3 - Don't say you weren't warned
01:30 PM Event 7 - I can't bear to look
02:30 PM Event 8 - Now that's gross
03:30 PM Event 9 - Hold your nose!
>:: Combine /INC and /EXC - List the morning events for Session 2
>jrepl "" "" /k 0 /inc "/^Session 2/+1:/^Session/-1" /exc "/ PM /" /f events.txt
10:00 AM Event 4 - Ouch, that's gotta hurt
11:00 AM Event 5 - The strongest man alive
>:: Use the offset feature when you already have important line numbers in variables
>:: and don't want to use SET /A to define another variable. In this case I want to
>:: list lines that appear after %begin%, and before %end%.
> set /a begin=5, end=9
9
>jrepl "" "" /k 0 /inc "%begin%+1:%end%-1" /f events.txt
01:00 PM Event 4
02:00 PM Event 5
03:00 PM Event 6
/P FilterRegexOnly search/replace strings that match the FilterRegex. This can be used with any type of search or search/replace.
The
/PFLAG option (not shown in examples) enables control over the g and i regular expression flags.
Multiline Mode Example:My
ADVENTURE.BAT port of collossal cave adventure selectively obfuscates code by applying the ROT13 cipher to text between curly braces. A simple JREPL command can quickly encode/decode the text, without requiring any user supplied JScript!
obfuscated.txtCode: Select all
:: Note that { boshfpngrq grkg
:: pna fcna yvarf } Pretty cool!
::{ Npgvingr qjneirf jura Unyy bs Zvfgf vf ernpurq }
if !#{qjnesFgngr}! equ 0 (
if !#{ybp}! geq 15 set /a #{qjnesFgngr}=1
goto :{qrfpevorYbpngvba}
)
Selectively decode the text
Code: Select all
jrepl "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"^
"nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"^
/t "" /p "{[^}]*}" /m /f obfuscated.txt
--RESULT--
Code: Select all
:: Note that { obfuscated text
:: can span lines } Pretty cool!
::{ Activate dwarves when Hall of Mists is reached }
if !#{dwarfState}! equ 0 (
if !#{loc}! geq 15 set /a #{dwarfState}=1
goto :{describeLocation}
)
Normal line based examples (back to the events.txt source):
Code: Select all
>:: Selectively mask all Session and Event titles
>jrepl "." "*" /p "- .*" /f events.txt
Session 1 ************************
07:00 AM Event 1 *************
08:00 AM Event 2 ******************
09:00 AM Event 3 **************************
Session 2 *****************************
10:00 AM Event 4 *************************
11:00 AM Event 5 *************************
12:00 PM Event 6 *****************************
Session 3 ******************************
01:00 PM Event 7 **********************
02:00 PM Event 8 ******************
03:00 PM Event 9 *****************
>:: /INC or /EXC (performed first) can be combined with /P (performed second)
>:: Only mask titles for Session 3
>:: Note how the /INC block continues to the end of file if the RangeEnd is not found
>jrepl "." "*" /inc "/^Session 3/:/^Session/" /p "- .*" /f events.txt
Session 1 - The mysteries of magic
07:00 AM Event 1 - Abracadabra
08:00 AM Event 2 - Where did it go?
09:00 AM Event 3 - How could you know that?
Session 2 - You won't believe your eyes
10:00 AM Event 4 - Ouch, that's gotta hurt
11:00 AM Event 5 - The strongest man alive
12:00 PM Event 6 - How can she bend like that?
Session 3 ******************************
01:00 PM Event 7 **********************
02:00 PM Event 8 ******************
03:00 PM Event 9 *****************
4) Improved PerformanceIn prior versions, many options made use of the JScript eval() function to execute user supplied code. This is comparatively quite slow, and especially has a large impact when it is used for each and every match.
I have managed to eliminate the use of eval() in any repetitive match code. I did this by dynamically defining a function with eval() only once, at the beginning, before any looping commences.
This gives a major performance boost to /T, /INC, and /EXC.
The code evaluated by eval() may contain many statements. The eval() function uses the value of the last statement (expression) as the return value. The /J and /JMATCH options rely on this behavior of eval(), so I could not modify how they are implemented.
So I added two new "Quick" options with similar functionality that take advantage of the new design.
/JQ - Functions the same as /J, except the code must store the return value in a variable named $txt.
/JMATCHQ - Functions the same as /JMATCH, except the code must store the return value in a variable named $txt.
Examples:
Code: Select all
>:: Old slow way with /J
>jrepl " [AP]M " "$0.toLowerCase()" /j /f events.txt
Session 1 - The mysteries of magic
07:00 am Event 1 - Abracadabra
08:00 am Event 2 - Where did it go?
09:00 am Event 3 - How could you know that?
Session 2 - You won't believe your eyes
10:00 am Event 4 - Ouch, that's gotta hurt
11:00 am Event 5 - The strongest man alive
12:00 pm Event 6 - How can she bend like that?
Session 3 - Don't say you weren't warned
01:00 pm Event 7 - I can't bear to look
02:00 pm Event 8 - Now that's gross
03:00 pm Event 9 - Hold your nose!
>:: New Quick way with /JQ
>jrepl " [AP]M " "$txt=$0.toLowerCase()" /jq /f events.txt
Session 1 - The mysteries of magic
07:00 am Event 1 - Abracadabra
08:00 am Event 2 - Where did it go?
09:00 am Event 3 - How could you know that?
Session 2 - You won't believe your eyes
10:00 am Event 4 - Ouch, that's gotta hurt
11:00 am Event 5 - The strongest man alive
12:00 pm Event 6 - How can she bend like that?
Session 3 - Don't say you weren't warned
01:00 pm Event 7 - I can't bear to look
02:00 pm Event 8 - Now that's gross
03:00 pm Event 9 - Hold your nose!
>:: Old slow way with /JMATCH
>jrepl "Event .* - (.*)" "$1.toUpperCase()" /jmatch /f events.txt
ABRACADABRA
WHERE DID IT GO?
HOW COULD YOU KNOW THAT?
OUCH, THAT'S GOTTA HURT
THE STRONGEST MAN ALIVE
HOW CAN SHE BEND LIKE THAT?
I CAN'T BEAR TO LOOK
NOW THAT'S GROSS
HOLD YOUR NOSE!
>:: New Quick way with /JMATCHQ
>jrepl "Event .* - (.*)" "$txt=$1.toUpperCase()" /jmatchq /f events.txt
ABRACADABRA
WHERE DID IT GO?
HOW COULD YOU KNOW THAT?
OUCH, THAT'S GOTTA HURT
THE STRONGEST MAN ALIVE
HOW CAN SHE BEND LIKE THAT?
I CAN'T BEAR TO LOOK
NOW THAT'S GROSS
HOLD YOUR NOSE!
Have fun with the new toys
Dave Benham