ashu
ashu

Reputation: 1357

Issues in using fart with batch script. Double forward slash and multiple occurrence

I am trying to create batch script that edits few java files in project due to some development environment issues. One of the files have text which needs to be commented.
So text (say abc(); ) will become commented text (//abc();).
Thus, I need to add double forward slash. I was trying to use find and replace text (FART) utility to replace text. But its creating issue with slashes. Any idea on how to proceed with this will be really helpful.

What I tried till yet:
fart.exe file.java abc(); //abc();
fart.exe -C file.java abc(); //abc();
fart.exe -C file.java "abc();" "//abc();"
fart.exe -C file.java abc(); ^/^/abc();
fart.exe -C file.java abc(); \/\/abc();
Unfortunately, none of them are working and I am out of ideas.


Taking help from link:

https://stackoverflow.com/questions/23359371/remove-slash-blackslash-using-fart

remove slash , blackslash using FART
I used
fart.exe -C file.java abc(); "\/\/abc();"
This works but also produces some warnings.

Secondly, is there restriction that only first instance can be replaced in fart. In a file, there were multiple occurrences and it printed 6 lines where occurrence was found but replaced none of them.

Thanks for helping me out.

Upvotes: 0

Views: 3089

Answers (2)

Ben Personick
Ben Personick

Reputation: 3264

I understand how that is and I've spent a long night and morning working on remembering how I did this last time and writing the script below for you.

I have worked mostly within that sphere for the last 10 years or so as I got sick the inconsistencies in VBScript, and needed to keep from using anything not available in the native OS wherever possible.

(It's only in the last 2 to 3 years that I feel confident enough that I will have most of the Powershell I need available to me, so I've begun to use it more Particularly for this type of issue)

So I spent several long hours through the night working on a version of the script which can replace the comments using native batch only.

This really took some doing as it has been at least a year ot two since I used this on anythign as complex as code which gives you all sorts of fun issues.

The below script should meet your needs using only native windows CMD Interpreter.

I have set the script to create a backup of the original files just in case I missed some scenario I didn't plan for.

I have the sample file I created and used and the example results are shown after the code below.

Fart.cmd Script:

REM Script: FART.cmd
REM Version: 0.9.3
REM Description: Replaces Text (Argument 2) with alternate Text (Argument 3) in File (Argement 1)
REM Example Usage: FART.cmd "C:\Admin\Stack_Exchange\40510701_FART\file.java" "abc();" "\\abc();"

@(
    SETLOCAL
    ECHO OFF
    SET "eLvl=0"
    SET "_FilePath=%~1"
    SET "_Find=%~2"
    SET "_Rep=%~3"
    SET "_ReFind=%~3"
    CALL :GetDateTime
)

CALL :Main

(
    ENDLOCAL
    Exit /b %eLvl%
)

:Main

    REM Set extra replace statement to keep commented matches at two comments depth if the replace string is a comment.
    IF /I "%_Rep:~0,2%" EQU "\\" (
        SET "_ReFind=\\%_Rep%"
    )

    REM Delete Temp File if it exists.
    DEL /F /Q "%_FilePath%.tmp"

    REM Make sure Delayed expantion is not turned on for the loop to interpret FindStr Correctly.
    REM Note:  Delayed expantion is diabled by default, however we're just being 'sure' as the FindStr prefix is needed to print blank lines correctly, so we can;t just use "type".
    SETLOCAL DISABLEDelayedExpansion

    FOR /F "Tokens=*" %%A IN ('Findstr /n "^" "%_FilePath%"') DO (

        SET "_Line=%%A"

        REM Enable Delayed expantion within the loop in order to process the line contents correctly.
        SETLOCAL ENABLEDelayedExpansion

        REM ECHO.
        REM Remove Prefix from Findstr.  (FindStr prefix is needed to print blank lines correctly)
        SET "_LineP=!_Line:*:=!"
        IF DEFINED _LineP (
            REM Replace + don't expand comments continually
            SET "_LineR=!_LineP:%_Find%=%_Rep%!"
            SET "_LineR=!_LineR:%_ReFind%=%_Rep%!"
        )
        REM ECHO.4
        REM ECHO.!_LineR!
        ECHO.!_LineR!>>"%_FilePath%.tmp"
        REM End the local delayed expantion environment while still within the loop.
        ENDLOCAL
    )

    REM End the local Non-Delayed expanion environement needed for the loop explicitly.
    ENDLOCAL

    REM Create a backup of the Original File for safety's sake.
    MOVE /Y "%_FilePath%" "%_FilePath%.%IsoDate%_%IsoTime%.bak"

    REM Move the temp file to replace the original File
    MOVE /Y "%_FilePath%.tmp" "%_FilePath%"
GOTO :EOF

:GetDateTime

    REM Note: I'm Tooting my own horn here, this took some doing:
    REM I created this Function to handle date and time across systems in different Regions.
    REM This gives the values both in their Zero Prefixed version, and in a version with the zero prefix stripped off so you can use it for calcuations.
    FOR /F "Tokens=1-7 delims=MTWFSmtwfsouehrandit:-\/. " %%A IN ("%DATE% %TIME: =0%") DO (
        FOR /F "Tokens=2-4 Skip=1 Delims=(-)" %%a IN ('ECHO.^| DATE') DO (
            SET "%%~a=%%~A"
            SET "%%~b=%%~B"
            SET "%%~c=%%~C"
            SET /a "#%%~a=1%%~A - (2%%~A-1%%~A)"
            SET /a "#%%~b=1%%~B - (2%%~B-1%%~B)"
            SET /a "#%%~c=1%%~C - (2%%~C-1%%~C)"
            SET "HH=%%~D"
            SET "Mn=%%~E"
            SET "SS=%%~F"
            SET "Ms=%%~G"
            SET /a "#HH=1%%~D - (2%%~D-1%%~D)"
            SET /a "#Mn=1%%~E - (2%%~E-1%%~E)"
            SET /a "#SS=1%%~F - (2%%~F-1%%~F)"
            SET /a "#Ms=1%%~G - (2%%~G-1%%~G)"
            SET /a "#TMinutes=((1%%~D - (2%%~D-1%%~D))*60)+(1%%~E - (2%%~E-1%%~E))"
            SET /a "#TSeconds=((((1%%~D - (2%%~D-1%%~D))*60)+(1%%~E - (2%%~E-1%%~E)))*60)+(1%%~F - (2%%~F-1%%~F))"
        )
    )
    SET "TTime=%HH%.%Mn%.%SS%"
    SET "IsoTime=%HH%.%Mn%.%SS%.%Ms%"
    SET "TDate=%yy%-%mm%-%dd%"
    SET "IsoDate=%yy%-%mm%-%dd%"
GOTO :EOF

Contents of the file I used for testing (Before change)

Hello there" Some stuff here"
"
""
{"orderNumber": "1476628690_2WOSU1OR"}<
more stuff here
the end
C:\Admin\Stack_Exchange\40071522

Powershell { $OldFile = get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" | %{$_ -replace 'abc();','\\abc();'}; $OldFile | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }

etrsyabc();
abc();
ghuoyuo | %{8p'\\abc();',hio[);'}
Powefuyo-cytonttgyientt4S ftilyte.javahkjtfy | JIxsdO;{$_ FGTacsde 'abc(YUOYT$YY);','\\$abc(7)$;'}TYTY
\abc();
abc()
abc()
abc();
wf \\abc();
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\\\*abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\\\*abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
 $Find='abc\(\)\;'; $Replace=''

Last line befoere 2 blank lines

Contents of the file I used for testing (After change)

Hello there" Some stuff here"
"
""
{"orderNumber": "1476628690_2WOSU1OR"}<
more stuff here
the end
C:\Admin\Stack_Exchange\40071522

Powershell { $OldFile = get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" | %{$_ -replace '\\abc();','\\abc();'}; $OldFile | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }

etrsy\\abc();
\\abc();
ghuoyuo | %{8p'\\abc();',hio[);'}
Powefuyo-cytonttgyientt4S ftilyte.javahkjtfy | JIxsdO;{$_ FGTacsde 'abc(YUOYT$YY);','\\$abc(7)$;'}TYTY
\\\abc();
abc()
abc()
\\abc();
wf \\abc();
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\\\*abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\\\*abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
 $Find='abc\(\)\;'; $Replace=''

Last line befoere 2 blank lines

Upvotes: 0

Ben Personick
Ben Personick

Reputation: 3264

I see you are open to alternatives? This is most easily done in Powershell these days, although I can write a cmd to make it work too, it's far more laborious to do so.

If you are open to using Powershell pop the following into your Admin-Enabled Command Prompt (no need to open a PowwerShell prompt):

Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\\\*abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }

Brief Note: I wanted to handle you re-running it on a file so I had to check so make sure you didn't keep adding braces to your text.

Upvotes: 0

Related Questions