0

I am trying to print Line 4, Col 21-50 out of a text file, can this be simply done under Windows somehow? I've been trying to do this:

FOR /F "usebackq tokens=1 delims=-" %G IN (%COMPUTERNAME%.txt) DO ECHO %G

This is just working out terribly. Can't I just print a specific set of lines?

I need this script to be run on multiple computers, ideally I'd like to convert it to a variable for use with slmgr -ipk, maybe someone has a better suggestion?

Contents of text file (I want the XXXXX-XXXXX-XXXXX-XXXXX-XXXXX portion):

==================================================
Product Name      : Windows 7 Professional
Product ID        : 00371-OEM-9044632-95844
Product Key       : XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
Installation Folder : C:\Windows
Service Pack      : Service Pack 1
Computer Name     : LIBRA
Modified Time     : 6/4/2015 7:26:54 PM
==================================================
aschipfl
  • 33,626
  • 12
  • 54
  • 99
ssgoku129
  • 3
  • 1
  • 2
  • `for /f "tokens=2 delims=:" %%# in (' type "\\skylab\Library\IT_Library\Utility\_keyfinder\%COMPUTERNAME%.txt"^|find /i "Product Key"') do slmgr -ipk%%#` is the command I needed with the help of npocmaka – ssgoku129 Aug 24 '15 at 19:39

2 Answers2

1

if you want only the "Product Key" line you can try with

type %COMPUTERNAME%.txt|find /i "Product Key"

or

for /f "tokens=2 delims=:" %%# in (' type %COMPUTERNAME%.txt^|find /i "Product Key"') do echo %%#
Stephan
  • 53,940
  • 10
  • 58
  • 91
npocmaka
  • 55,367
  • 18
  • 148
  • 187
  • I keep getting "%%# was unexpected at this time." when I run the for/do command but I was hoping to trim the "Product Key :" from the output so I could parse the output into slmgr -ipk – ssgoku129 Aug 24 '15 at 18:31
  • this syntax is for use in batch files. For use at the command prompt, use a single `%` (`%#` instead of `%%#`) – Stephan Aug 24 '15 at 18:37
  • Oops sorry, fixed the cmd but I'm getting this error now: | was unexpected at this time. – ssgoku129 Aug 24 '15 at 18:56
  • 1
    Try again. There was a typo (missing caret). – Stephan Aug 24 '15 at 19:08
  • That is exactly what I need, now I just have to figure out how to parse that output into SLMGR -ipk for an easy product key installation script, thanks so much! – ssgoku129 Aug 24 '15 at 19:19
1

For the task at hand, npocmaka's answer is the best suitable approach, as it does not insist on a fixed position of the string to extract from the file.
However, I want to provide a variant that sticks to a certain position.

The following code extracts the string placed at columns 21 to 50 in line 4 of file list.txt (the result is echoed (enclosed in "") and stored in variable LINE_TXT (without ""):

@echo off

for /F "tokens=1,* delims=:" %%L in (
  'findstr /N /R ".*" "list.txt"'
) do (
  if %%L equ 4 (
    set "LINE_TXT=%%M"
    goto :NEXT
  )
)
:NEXT
if defined LINE_TXT set "LINE_TXT=%LINE_TXT:~20,29%"
echo."%LINE_TXT%"

The goto :NEXT command terminates the for /F loop at the given line; this is not mandatory but will improve performance for huge files (as long as the given line number is quite small).

To be more flexible, the following code can be used (define the string position in the initial set block):

@echo off

rem Define the string position here:
set FILE_TXT="list.txt"
set LINE_NUM=4
set COL_FROM=21
set COL_UPTO=50

setlocal EnableDelayedExpansion
set /A COL_UPTO-=COL_FROM
set /A COL_FROM-=1
for /F "tokens=1,* delims=:" %%L in (
  'findstr /N /R ".*" %FILE_TXT%'
) do (
  if %%L equ %LINE_NUM% (
    set "LINE_TXT=%%M"
    if defined LINE_TXT (
      set "LINE_TXT=!LINE_TXT:~%COL_FROM%,%COL_UPTO%!"
    )
    goto :NEXT
  )
)
:NEXT
endlocal & set "LINE_TXT=%LINE_TXT%"
echo."%LINE_TXT%"

Both of the above code snippets rely on the output of findstr /N /R ".*", which returns every line that matches the regular expression .*, meaning zero or more characters, which in turn is actually true for every line in the file; however, the switch /N defines to prefix each line with its line number, which I extract and compare with the originally defined one.


Here is another variant which uses for /F to directly loop through the content (lines) of the given text file, without using findstr:

@echo off

for /F "usebackq skip=3 eol== delims=" %%L in (
  "list.txt"
) do (
  set "LINE_TXT=%%L"
  goto :NEXT
)
:NEXT
if defined LINE_TXT set "LINE_TXT=%LINE_TXT:~20,29%"
echo."%LINE_TXT%"

This method has got the better performance, because there is the skip option which skips parsing of and iterating through all lines (1 to 3) before the line of interest (4), opposed to the findstring variant.
However, there is one disadvantage: for /F features an eol option which defines a character interpreted as line comment (and defaults to ;); there is no way to switch this option off as long as delims= defines no delimiters (last position in option string), which is mandatory here to return the line as is; so you have to find a character that does not appear as the first one in any line (I defined = here because your sample text file uses this as header/footer character only).

To extract a string from line 1, remove the skip option as skip=0 results in a syntax error.

Note that goto :NEXT is required here; otherwise, the last (non-empty) line of the file is extracted.

Although for /F does not iterate any empty lines in the file, this is no problem here as the skip option does not check the line content and skip over empty lines as well.


Finally, here is one more approach using more +3 where no text parsing is done. However, a temporary file is needed here to pass the text of the desired line to the variable LINE_TXT:

@echo off
set LINE_TXT=
more +3 "list.txt" > "list.tmp"
set /P LINE_TXT= < "list.tmp"
del /Q "list.tmp"
if defined LINE_TXT set "LINE_TXT=%LINE_TXT:~20,29%"
echo."%LINE_TXT%"
exit /B 0

This method avoids for /F and therefore the problem with the unwanted eol option as mentioned in the above solution. But this does not handle tabs correctly as more substitutes them with spaces (8 indent spaces as per default and configurable by the /Tn switch where n is the number of spaces).

Community
  • 1
  • 1
aschipfl
  • 33,626
  • 12
  • 54
  • 99
  • I just found an interesting approach to extract a certain line from a text file [here](http://stackoverflow.com/a/6410343/5047996) using `more +n`... – aschipfl Aug 24 '15 at 20:15
  • cool! it's interesting to play around with these, I prefer the one that doesn't use findstr as it seemed to execute the slmgr command the fastest, I'll try the tempfile one just for learning sake, here's the cmd I used from your 3rd example: `@echo off for /F "usebackq skip=3 eol== delims=" %%L in ( "\\skylab\Library\IT_Library\Utility\_keyfinder\%COMPUTERNAME%.txt" ) do ( set "LINE_TXT=%%L" goto :NEXT ) :NEXT set "LINE_TXT=%LINE_TXT:~20,29%" slmgr -ipk "%LINE_TXT%"` – ssgoku129 Aug 24 '15 at 21:02