0

Hope I will be clear with my problem and what I search for. I have a long script in a .sjs file (basically txt with different extension), part of which are the following lines. In the comments below this is either referred to as input.txt or Builder.sjs

var Want_spring_aid_file_update = 0;
var Front_spring_aid_file = "name_1.pspck";
var Rear_spring_aid_file = "name_2.pspck";

I have been looking around for a .bat script that can probe certain lines, 2 and 3 in the case above, in this .sjs file and write the string between double quotes in a text new file. In the comments below this new text file is referred to as comments.txt.

I have found on this marvelous website a script that outputs all the strings between quotes in that file. I want just on particular lines. The script I am talking about is below.

>"output.txt" (
 for /f usebackq^ tokens^=2^ delims^=^" %%A in ("input.txt") do echo "%%A" 
)

Also It would be helpful is someone could help me understand the role of certain characters in the above script. These are ^, 2^, ^=^.

Thanks guys !

CristianCapsuna
  • 392
  • 3
  • 14
  • Instead of using `"input.txt"` why not use `'FindStr [options] [search mask] "input.txt"'` to just pick out the data related to your required `var` names? – Compo Aug 14 '17 at 16:10
  • This do the trick with the shown data: `for /F "skip=1 tokens=4 delims=; " %%a in (test.txt) do echo %%~a`. The `skip=1` part omits line 1. `"tokens=4 delims=; "` takes the 4th token delimited by spaces or semicolon. The inclusion of a tilde in `%%~a` part show such a token removing enclosing quotes. – Aacini Aug 15 '17 at 02:15

2 Answers2

1

@Compo thanks! The following code did it after a bit of trial and error.

@echo off
>>"comments.txt" ( 
    for /f usebackq^ tokens^=2^ delims^=^" %%A in ( 'findstr /C:var Front_spring_aid_file = ^"part_name1^"; "Builder.sjs"') do echo %%A
)
CristianCapsuna
  • 392
  • 3
  • 14
  • The `findstr` command line results in searching for the string `var` in the files `Front_spring_aid_file`, `=`, `part_name1;` and `Builder.sjs`. To find the line with variable `Front_spring_aid_file` it is necessary to use for example `findstr /C:"var Front_spring_aid_file =" "Builder.sjs"` because this results in searching in file `Builder.sjs` for a line containing the string `var Front_spring_aid_file =`. – Mofi Aug 15 '17 at 09:08
  • To search for a line containing the string `var Front_spring_aid_file = "part_name1";` it is necessary to use the command line `findstr /L /C:"var Front_spring_aid_file = \"part_name1\";" "Builder.sjs"`. But I doubt if it makes sense to search for more or less an entire line as in this case the output of `findstr` is the same as the search string. Better would be using a regular expression as with `findstr /R /C:"var  *Front_spring_aid_file *= *\"..*\";" "Builder.sjs"`. Run `findstr /?` in a command prompt window for help on this regular expression search. – Mofi Aug 15 '17 at 09:19
  • @Mofi . Complicated stuff indeed. It does work and I believe it works because the switch `/C:` tells the `findstr` function to ignore the spaces in the string that follows and thus it goes up tot he next `"` without an escape in front of it, in this case this being the " in front of `"Builder.sjs"`. If I write it as `'findstr /C:"var Front_spring_aid_file = ^"part_name1^";" "Builder.sjs"'` it says the sintax is incorrect. BTW thanks for noticing my small part name leak. – CristianCapsuna Aug 15 '17 at 09:23
  • @Mofi If i replace the `findstr` in mine with the one you suggested which includes the switch `/L` the output is var Front_spring_aid_file = \ – CristianCapsuna Aug 15 '17 at 09:27
  • No, `/C:"search string with spaces"` must be used to search for a literal string containing also spaces. Try it out with running just the `findstr` command line in a command prompt window in directory containing the file `Builder.sjs` as I have done too. You just think it works as expected because __FOR__ filters the wrong output of __FINDSTR__ to the expected output. The escape character in a search string of __FINDSTR__ is ``\``. But this enables by default a regular expression search which is the reason why `/L` must be also specified to explicitly request a literal search. – Mofi Aug 15 '17 at 09:28
  • @Mofi Apparently the code I posted works even if you don't use the escapes `^` in front of the `"` in the string to be searched for. Now that is weird. – CristianCapsuna Aug 15 '17 at 09:30
  • The opposite is using the option `/R` to instruct __FINDSTR__ that the search string is a regular expression string and therefore a regular expression search should be used. We could safe both our time if you edit your question and explain with a better example what you want to search for in `Builder.sjs` respectively `input.txt`, which lines should be found by the search string and what should be finally written into the output file from the found lines. – Mofi Aug 15 '17 at 09:31
  • You need to learn that each application interprets the argument strings on command line different. There is no general rule used by `cmd.exe` and `findstr.exe` and all other console applications how to interpret the rest of the line after command or executable name. I demonstrated and explained that [here](https://stackoverflow.com/a/24008269/3074564) and [here](https://stackoverflow.com/a/34402887/3074564). You are confused because you think what works for `for` interpreted by `cmd.exe` works also for `findstr.exe`, but that is not true. Run `findstr /?` and read about `^`. – Mofi Aug 15 '17 at 09:41
  • @Mofi Thanks for the help and for the references. I believe you and I will look into it later this evening (it 11 AM now where I am) as I want to understand things properly but for the moment for some reason that works and I have to crack on with what I have to do at work. Once I understand things I am sure I will come back with some more questions. I would be very grateful for you guidance when that happens. – CristianCapsuna Aug 15 '17 at 09:50
0

The command FOR with option /F is used to process lines of a file, or a single string specified in double quotes, or output of a command line executed by FOR in a separate command process in background captured from handle STDOUT of this background command process.

The first option usebackq results in interpreting the file name specified in double quotes not as string to process, but as double quoted name of a file of which lines should be processed by FOR.

The option delims= is used to specify the delimiters for splitting each non empty line not starting with default end of line character ; up into one or more substrings called tokens. The default delimiters are space and horizontal tab character. delims= without any character means do not split up the line at all. Only the double quote character " should be used for this task as delimiter.

The option tokens= defines which substring(s) should be assigned to the loop variable(s). By default only the first substring (token) is assigned to the specified loop variable. By specifying tokens=2 the command FOR is informed that of interest is the second substring which should be assigned to the specified loop variable (first). This means also if a line does not have a string after 1 or more of the specified delimiters, the line is also ignored. This is true for the first line of input.txt which does not contain a double quote character at all.

Run in a command prompt window for /? for more information about the options of command FOR output on several pages.

Those options of FOR are specified usually enclosed in double quotes.

>"output.txt" (
    for /F "usebackq tokens=2 delims="" %%A in ("input.txt") do echo "%%A" 
)

But the problem here is specifying " as delimiter. For Windows command interpreter the option string is "usebackq tokens=2 delims=" which would not make much sense because that means the lines should not be split up into tokens and nevertheless only the second token is of interest. However, the next " is invalid because expected next is the loop variable, a single character with a percent sign before. The percent sign must be escaped in a batch file with an additional percent sign.

For that reason it is necessary to specify the options of FOR without enclosing them in double quotes. So it must be made sure during the preprocessing phase of Windows command interpreter before executing the FOR command line that the 3 options are interpreted as a single argument string.

The escape character to use in batch files is the caret character ^ which instructs Windows command interpreter to interpret the next character as literal character belonging to an argument string. Only % must be escaped with % instead of ^ to be interpreted as literal character.

It can be read on running in a command prompt window cmd /? on last paragraph on last output help page which characters in directory/file names (or other argument strings) require enclosing the string in double quotes: the space character, the characters &()[]{}^=;!'+,`~ and not mentioned by help the characters "|<> which can't be used in a directory/file name.

So it is specified with usebackq^ tokens^=2^ delims^=^" for Windows command interpreter that an argument string not enclosed in double quotes with the unusual text usebackq tokens=2 delims=" should be passed to command FOR as second argument after /F.

Windows command interpreter interprets a space character and an equal sign not escaped with ^ as delimiter between argument strings.

A double quote not escaped with ^ is interpreted as begin of an argument string which ends with another double quote and all characters between with exception of % and ! when delayed expansion is enabled are interpreted as literal characters.

That is the reason why the spaces characters, the equal signs and the double quote must be escaped with ^ in the argument string usebackq tokens=2 delims=".

See How does the Windows Command Interpreter (CMD.EXE) parse scripts? for more detailed information about command line parsing by Windows command interpreter.

Mofi
  • 46,139
  • 17
  • 80
  • 143
  • Hi Mofi! Thanks a lot for the clarification. I am now clear on what "^" does but am still a bit in doubt about its position.As in why is appears after the the number 2 and before a space. This however did now say how to solve my problem. However the solution mentioned by @Compo worked after a bit of trial and error – CristianCapsuna Aug 15 '17 at 08:13