I am trying to replace only the first match in a text file.
My code is:
FOR /R %%a IN ("*.out") DO call C:\qsi\jrepl.bat "FF**********" "**********" /f "%%a" /L /m /o -
The FF before the asterisks is representing a form feed character.
The code is for removing the form feed for the first match only.
I was trying to play with /p
& /pflag "i"
, but could not get it to work.
I am using the latest version 8.2 of JREPL.BAT.
It is possible to use the JREPL.BAT option /INC
if the first form feed is within a specific block at top of a text file and there is never one more form feed in same block.
Example for first form feed within the lines 3 to 10:
@echo off
for /R %%I in ("*.out") do call C:\qsi\jrepl.bat "\f" "" /INC "3:10" /F "%%I" /O -
The JScript regular expression search string \f
matches a form feed control character.
The replace string is an empty string to remove the form feed in this include block.
The option /L
for a literal search cannot be used on using \f
or alternatively \x0C
(hexadecimal value of form feed control character) in search string.
The option /M
cannot be used on using option /INC
as explained by help output on running JREPL.BAT in a command prompt window with /?
or /??
. The lines respectively the line endings must be detected and counted to identify the block from line 3 to line 10 on which the replace should be done and nothing outside this block.
A solution using option /PFLAG
is also possible by using:
for /R %%I in ("*.out") do call C:\qsi\jrepl.bat "\f" "" /M /P "\f" /PFLAG "" /F "%%I" /O -
JREPL.BAT runs a JScript regular expression replace with these options searching for a form feed character in entire file because of option /M
. It replaces only first form feed because of using the option /PFLAG ""
which means running the case-sensitive replace without flag g
for a non-global replace.
But it is necessary to specify also option /P
with a regular expression string in addition to the regular expression search string specified as first argument for usage of option /PFLAG
with empty flag string ""
or with "i"
for a non-global case-insensitive search. In this case the additional regular expression after /P
is the same as the main search expression, just \f
to match a form feed, the first form feed in entire file.
UPDATE:
The real task is to remove in a binary file first and only occurrence of the byte sequence 1B 45
and first occurrence of 0C
being always after 1B 45
with keeping all other 0C
in file. The binary file contains for example beginning at byte offset 752 (hexadecimal 02F0) the bytes:
02F0h: F8 00 FC 01 F8 00 0D 0A 0D 1B 45 1B 28 73 30 70 ; ø.ü.ø.....E.(s0p 0300h: 30 73 33 62 31 32 68 34 31 30 31 54 1B 26 6C 32 ; 0s3b12h4101T.&l2 0310h: 61 30 6F 30 65 30 6C 38 64 38 38 46 0D 0A 1B 2A ; a0o0e0l8d88F...* 0320h: 70 30 78 30 59 1B 2A 63 35 37 36 30 78 37 39 32 ; p0x0Y.*c5760x792 0330h: 30 59 1B 2A 63 30 54 1B 25 31 42 53 50 31 3B 53 ; 0Y.*c0T.%1BSP1;S 0340h: 43 30 2C 33 2E 33 38 36 37 2C 30 2C 2D 33 2E 33 ; C0,3.3867,0,-3.3 0350h: 38 36 37 2C 32 3B 49 52 30 2C 31 30 30 2C 30 2C ; 867,2;IR0,100,0, 0360h: 31 30 30 3B 53 50 31 3B 44 54 5E 2C 31 3B 53 44 ; 100;SP1;DT^,1;SD 0370h: 32 2C 31 2C 34 2C 31 30 2C 35 2C 30 2C 36 2C 33 ; 2,1,4,10,5,0,6,3 0380h: 2C 37 2C 34 31 34 38 3B 1B 25 31 41 0D 0A 0D 0A ; ,7,4148;.%1A.... 0390h: 0C 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A ; .*************** 03A0h: 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A ; **************** 03B0h: 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A ; **************** 03C0h: 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A ; **************** 03D0h: 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 0D 0A 0D ; *************... 03E0h: 0A 62 6C 61 68 20 62 6C 61 68 20 62 6C 61 68 0D ; .blah blah blah. 03F0h: 0A 0D 0A 0C 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A ; ....************
This block should be modified to:
02F0h: F8 00 FC 01 F8 00 0D 0A 0D 1B 28 73 30 70 30 73 ; ø.ü.ø.....(s0p0s 0300h: 33 62 31 32 68 34 31 30 31 54 1B 26 6C 32 61 30 ; 3b12h4101T.&l2a0 0310h: 6F 30 65 30 6C 38 64 38 38 46 0D 0A 1B 2A 70 30 ; o0e0l8d88F...*p0 0320h: 78 30 59 1B 2A 63 35 37 36 30 78 37 39 32 30 59 ; x0Y.*c5760x7920Y 0330h: 1B 2A 63 30 54 1B 25 31 42 53 50 31 3B 53 43 30 ; .*c0T.%1BSP1;SC0 0340h: 2C 33 2E 33 38 36 37 2C 30 2C 2D 33 2E 33 38 36 ; ,3.3867,0,-3.386 0350h: 37 2C 32 3B 49 52 30 2C 31 30 30 2C 30 2C 31 30 ; 7,2;IR0,100,0,10 0360h: 30 3B 53 50 31 3B 44 54 5E 2C 31 3B 53 44 32 2C ; 0;SP1;DT^,1;SD2, 0370h: 31 2C 34 2C 31 30 2C 35 2C 30 2C 36 2C 33 2C 37 ; 1,4,10,5,0,6,3,7 0380h: 2C 34 31 34 38 3B 1B 25 31 41 0D 0A 0D 0A 2A 2A ; ,4148;.%1A....** 0390h: 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A ; **************** 03A0h: 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A ; **************** 03B0h: 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A ; **************** 03C0h: 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A ; **************** 03D0h: 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 0D 0A 0D 0A 62 6C ; **********....bl 03E0h: 61 68 20 62 6C 61 68 20 62 6C 61 68 0D 0A 0D 0A ; ah blah blah.... 03F0h: 0C 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A ; .***************
So the task is to remove the two bytes 1B 45
at byte offset 761 (hexadecimal 02F9) and the byte 0C
at byte offset 912 (hexadecimal 0390) without removing any other byte 0C
like the one at byte offset 1011 (hexadecimal 03F3).
The following command line can be used in a batch file for removing in such binary files containing ESC+E stored hexadecimal with the bytes 1B 45
and first Form Feed stored hexadecimal with the byte 0C
:
for /R %%I in ("*.out") do call C:\qsi\jrepl.bat "\x1BE([\s\S]+?)\f" "$1" /M /F "%%I" /O -
The regular expression search string results in searching for
\x1BE
... a byte with hexadecimal value 1B
followed by character E
(case-sensitive) and(
...)
... with using a marking group[\s\S]
... for a whitespace or a non-whitespace character, i.e. any character (or byte)+
... one or more times?
... non-greedy\f
... and a form feed.The bytes between 1B 45
and 0C
matched by the expression inside marking group are back-referenced in replace string with $1
to be kept in the binary files.