Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
要回显特定行号的Windows批处理文件_Windows_Batch File - Fatal编程技术网

要回显特定行号的Windows批处理文件

要回显特定行号的Windows批处理文件,windows,batch-file,Windows,Batch File,因此,对于我当前困境的第二部分,我在c:\file\u list.txt中有一个文件夹列表。我需要能够根据行号提取它们(好吧,用一些mod来回送它们),因为这个批处理脚本是由迭代宏过程调用的。我把行号作为参数传递 @echo off setlocal enabledelayedexpansion set /a counter=0 set /a %%a = "" for /f "usebackq delims=" %%a in (c:\file_list.txt) do ( if "!cou

因此,对于我当前困境的第二部分,我在
c:\file\u list.txt
中有一个文件夹列表。我需要能够根据行号提取它们(好吧,用一些mod来回送它们),因为这个批处理脚本是由迭代宏过程调用的。我把行号作为参数传递

@echo off
setlocal enabledelayedexpansion
set /a counter=0
set /a %%a = ""
for /f "usebackq delims=" %%a in (c:\file_list.txt) do (
   if "!counter!"=="%1" goto :printme & set /a counter+=1
)
:printme
echo %%a
这给了我一个
%a
的输出。啊!所以,我试着回应
!a(结果:
回声关闭。
);我尝试回显
%a
(结果:a)

我想最简单的方法是修改
head.bat
代码:

除了不重复每一行,我只重复最后一行。并不像人们想象的那么简单。我注意到由于某种原因,我的计数器一直保持在零;我想知道
设置/a计数器+=1
是否正在做我认为它正在做的事情。

呸,它吃掉了我的格式

@echo off

setlocal enabledelayedexpansion

set /a counter=0
set %%a = ""

for /f "usebackq delims=" %%a in (c:\file_list.txt) do (if "!counter!"=="%1" goto :printme & set /a counter+=1)

:printme

echo %%a%

我知道这是一个老问题,但这里有一些类似问题的其他信息

Lee,您关于“%%a”在for循环之外不起作用的推理是正确的。%a-z和%a-z变量(%%a-z在批处理文件中)是for循环的构造,不存在于for循环之外

我想推荐一种解决此问题的替代方案,它匹配正确的行号(不跳过空行),并且不需要延迟扩展、计数器或goto语句。请看下面的代码:

@echo off
for /f "tokens=1* delims=:" %%a in ('findstr /n .* "c:\file_list.txt"') do if "%%a"=="%1" set line=%%b
echo.%line%
以下是导致我做出上述改变的原因。假设您有以下文件内容:

Some text on line 1
Blah blah blah
More text
我做的第一件事是将(c:\file\u list.txt)更改为('findstr/n.*.c:\file\u list.txt')

  • findstr/n.*”PATH\FILENAME“”读取文件并在每一行中添加行号(“/n”)(“*”是与任何字符的“0或更多”匹配的正则表达式)。因为现在每一行的开头都有一个行号(即使是空的行号),所以for循环不会跳过任何行
现在,for循环中的每一行都将如下所示:

1:Some text on line 1
2:Blah blah blah
3:More text
接下来,我们使用“tokens=1*delims=:”来分解行号和内容

  • tokens=1*”将第一个标记(存储在%%a中)设置为分隔符前面的所有内容,将第二个标记(存储在%%b中)设置为分隔符后面的所有内容
  • delims=:”将“”设置为分隔字符串的分隔符
现在,当我们在文件中循环时,%%a将返回当前行号,%%b将返回该行的内容

剩下的就是将%1参数与%%a(而不是计数器变量)进行比较,并使用%%b存储当前行内容:如果“%%a”=“%1”设置行=%%b

一个额外的好处是“<强> EnabelDelayExtPusith<<强>”不再是必要的,因为上面的代码消除了for循环中间的计数器变量。

编辑:将“echo%line%”更改为“echo.%line%”。这将正确显示空行,而不是“ECHO已关闭”。将“类型c:\file_list.txt^ findstr/n.*”更改为“findstr/n.*”c:\file_list.txt“”,因为findstr命令已经可以直接读取文件

杰布,我想我已经解决了所有的性格问题。试一试:

for /f "tokens=*" %%a in ('findstr /n .* "c:\file_list.txt"') do (
  set "FullLine=%%a"
  for /f "tokens=1* delims=:" %%b in ("%%a") do (
    setlocal enabledelayedexpansion
    set "LineData=!FullLine:*:=!"
    if "%%b" equ "%1" echo(!LineData!
    endlocal
  )
)

您可以使用如下批处理函数:

@ECHO OFF
CALL :ReadNthLine "%~nx0" 10
PAUSE >NUL
GOTO :EOF

:ReadNthLine File nLine
FOR /F "tokens=1* delims=]" %%A IN ('^<"%~1" FIND /N /V "" ^| FINDSTR /B /C:"[%2]"') DO ECHO.%%B
GOTO :EOF

A line containing special shell characters: () <> %! ^| "&
:ReadNthLine File nLine
FOR /F %%A IN ('^<"%~1" FIND /C /V ""') DO IF %2 GTR %%A (ECHO Error: No such line %2. 1>&2 & EXIT /b 1)
FOR /F "tokens=1* delims=]" %%A IN ('^<"%~1" FIND /N /V "" ^| FINDSTR /B /C:"[%2]"') DO ECHO.%%B
EXIT /b
@ECHO关闭
调用:ReadNthLine“%~nx0”10
暂停>NUL
后藤:EOF
:ReadNthLine文件nLine

对于('^中的/F“tokens=1*delims=]”%%A,有一个技巧可以提取不带行号前缀的行字符串(如果愿意,也可以使用),并且不需要对所有文件行使用批处理迭代(“FOR/F”加上计数)

为此,您必须在管道中始终使用findstr.exe,并通过
/B/C:“:”/C:“:”../C:“
参数通过管道中的第二个findstr.exe对行进行反筛选

这里是我用来解析文本和二进制文件的print_file_string.bat脚本:

@echo off

rem Description:
rem   Script for string lines extraction from a text/binary file by findstr
rem   utility pattern and/or line number.

rem Command arguments:
rem %1 - Optional flags:
rem      -n - prints line number prefix "<N>:" for each found string from file.
rem           By default, the line number prefix does not print.
rem      -f1 - filter by line numbers for strings after %4..%N filter pattern.
rem           By default, filters by line numbers from the file.
rem      -pe - treats input file as a Portable Executable file
rem           (the strings.exe must exist).
rem           By default, the file treated as a text file.
rem %1 - Path to a directory with a file to extract.
rem %2 - Relative path to a text/binary file with strings.
rem %3 - Set of line numbers separated by : character to print strings of.
rem      These line numbers by default are line numbers of strings from the
rem      file, not from filtered output. If you want to point line numbers
rem      after %4..%N filter pattern, then you must use -f1 flag.
rem      If empty, then treated as "all strings".
rem %4..%N - Arguments for findstr command line in first filter.
rem      If empty, then treated as /R /C:".*", which means "any string".

rem CAUTION:
rem   DO NOT use /N flag in %4..%N arguments, instead use script -n flag to
rem   print strings w/ line number prefix.

rem Examples:
rem 1. call print_file_string.bat -n . example.txt 1:20:10:30 /R /C:".*"
rem Prints 1, 10, 20, 30 lines of the example.txt file sorted by line number
rem and prints them w/ line number prefix:
rem
rem 2. call print_file_string.bat . example.txt 100 /R /C:".*"
rem Prints 100'th string of example.txt file and prints it w/o line number
rem prefix.
rem
rem 3. call print_file_string.bat -pe c:\Application res.dll "" /B /C:"VERSION="
rem Prints all strings from the c:\Application\res.dll binary file, where
rem strings beginning by the "VERSION=" string and prints them w/o line number
rem prefix.
rem
rem 4. call print_file_string.bat -pe c:\Application res.dll 1:20:10:30 /R /C:".*"
rem Prints 1, 10, 20, 30 lines of string resources from the
rem c:\Application\res.dll binary file, where strings beginning by the
rem "VERSION=" string and prints them w/o line number prefix.

setlocal EnableDelayedExpansion

set "?~dp0=%~dp0"
set "?~nx0=%~nx0"

rem script flags
set FLAG_PRINT_LINE_NUMBER_PREFIX=0
set FLAG_F1_LINE_NUMBER_FILTER=0
set FLAG_FILE_FORMAT_PE=0

rem flags
set "FLAGS="

:FLAGS_LOOP

rem flags always at first
set "FLAG=%~1"

if not "%FLAG%" == "" ^
if not "%FLAG:~0,1%" == "-" set "FLAG="

if not "%FLAG%" == "" (
  if "%FLAG%" == "-n" set FLAG_PRINT_LINE_NUMBER_PREFIX=1
  if "%FLAG%" == "-f1" set FLAG_F1_LINE_NUMBER_FILTER=1
  if "%FLAG%" == "-pe" set FLAG_FILE_FORMAT_PE=1
  shift

  rem read until no flags
  goto FLAGS_LOOP
)

set "DIR_PATH=%~dpf1"
set "FILE_PATH=%~2"

set "FILE_PATH_PREFIX="
if not "%DIR_PATH%" == "" set "FILE_PATH_PREFIX=%DIR_PATH%\"

if not "%FILE_PATH_PREFIX%" == "" ^
if not exist "%FILE_PATH_PREFIX%" (
  echo.%?~nx0%: error: Directory path does not exist: "%FILE_PATH_PREFIX%"
  exit /b 1
) >&2

if "%FILE_PATH%" == "" (
  echo.%?~nx0%: error: File path does not set.
  exit /b 2
) >&2

if not exist "%FILE_PATH_PREFIX%%FILE_PATH%" (
  echo.%?~nx0%: error: File path does not exist: "%FILE_PATH_PREFIX%%FILE_PATH%"
  exit /b 3
) >&2

set "LINE_NUMBERS=%~3"

set "FINDSTR_LINES_FILTER_CMD_LINE="
if "%LINE_NUMBERS%" == "" goto FINDSTR_LINES_FILTER_END

set LINE_NUMBER_INDEX=1
:FINDSTR_LINES_FILTER_LOOP
set "LINE_NUMBER="
for /F "tokens=%LINE_NUMBER_INDEX% delims=:" %%i in ("%LINE_NUMBERS%") do set "LINE_NUMBER=%%i"
if "%LINE_NUMBER%" == "" goto FINDSTR_LINES_FILTER_END

set FINDSTR_LINES_FILTER_CMD_LINE=!FINDSTR_LINES_FILTER_CMD_LINE! /C:"!LINE_NUMBER!:"
set /A LINE_NUMBER_INDEX+=1
goto FINDSTR_LINES_FILTER_LOOP

:FINDSTR_LINES_FILTER_END

shift
shift
shift

set "FINDSTR_FIRST_FILTER_CMD_LINE="

:FINDSTR_FIRST_FILTER_LOOP
set ARG=%1

if not "!ARG!" == "" (
  set FINDSTR_FIRST_FILTER_CMD_LINE=!FINDSTR_FIRST_FILTER_CMD_LINE! !ARG!
  shift
  goto FINDSTR_FIRST_FILTER_LOOP
)

if "!FINDSTR_FIRST_FILTER_CMD_LINE!" == "" set FINDSTR_FIRST_FILTER_CMD_LINE=/R /C:".*"

set OUTPUT_HAS_NUMBER_PREFIX=0

rem in case if /N at the end
set "FINDSTR_FIRST_FILTER_CMD_LINE=!FINDSTR_FIRST_FILTER_CMD_LINE! "

rem 1. add /N parameter to first filter if must print line prefixes and -f1 flag is not set.
rem 2. flags prefixed output if must print line prefixes.
if %FLAG_PRINT_LINE_NUMBER_PREFIX% NEQ 0 (
  if %FLAG_F1_LINE_NUMBER_FILTER% EQU 0 (
    if "!FINDSTR_FIRST_FILTER_CMD_LINE:/N =!" == "!FINDSTR_FIRST_FILTER_CMD_LINE!" (
      set "FINDSTR_FIRST_FILTER_CMD_LINE=/N !FINDSTR_FIRST_FILTER_CMD_LINE!"
    )
  )
  set OUTPUT_HAS_NUMBER_PREFIX=1
)

rem 1. add /N parameter to first filter and flags prefixed output if lines filter is not empty and -f1 flag is not set.
rem 2. add /B parameter to lines filter if lines filter is not empty
if not "!FINDSTR_LINES_FILTER_CMD_LINE!" == "" (
  if %FLAG_F1_LINE_NUMBER_FILTER% EQU 0 (
    if "!FINDSTR_FIRST_FILTER_CMD_LINE:/N =!" == "!FINDSTR_FIRST_FILTER_CMD_LINE!" (
      set "FINDSTR_FIRST_FILTER_CMD_LINE=/N !FINDSTR_FIRST_FILTER_CMD_LINE!"
      set OUTPUT_HAS_NUMBER_PREFIX=1
    )
  )
  if "!FINDSTR_LINES_FILTER_CMD_LINE:/B =!" == "!FINDSTR_LINES_FILTER_CMD_LINE!" (
    set "FINDSTR_LINES_FILTER_CMD_LINE=/B !FINDSTR_LINES_FILTER_CMD_LINE!"
  )
)

rem 1. remove /N parameter from first filter if -f1 flag is set.
rem 2. flags prefixed output if -f1 flag is set.
if %FLAG_F1_LINE_NUMBER_FILTER% NEQ 0 (
  if not "!FINDSTR_FIRST_FILTER_CMD_LINE:/N =!" == "!FINDSTR_FIRST_FILTER_CMD_LINE!" (
    set "FINDSTR_FIRST_FILTER_CMD_LINE=!FINDSTR_FIRST_FILTER_CMD_LINE:/N =!"
  )
  set OUTPUT_HAS_NUMBER_PREFIX=1
)

if "%TOOLS_PATH%" == "" set "TOOLS_PATH=%?~dp0%"
rem set "TOOLS_PATH=%TOOLS_PATH:\=/%"
if "%TOOLS_PATH:~-1%" == "\" set "TOOLS_PATH=%TOOLS_PATH:~0,-1%"

if %FLAG_FILE_FORMAT_PE% EQU 0 (
  set CMD_LINE=type "%FILE_PATH_PREFIX%%FILE_PATH%" ^| findstr !FINDSTR_FIRST_FILTER_CMD_LINE!
) else (
  rem add EULA acception into registry to avoid EULA acception GUI dialog
  reg add HKCU\Software\Sysinternals\Strings /v EulaAccepted /t REG_DWORD /d 0x00000001 /f >nul 2>nul

  rem @ for bug case workaround
  set CMD_LINE=@"%TOOLS_PATH%\strings.exe" -q "%FILE_PATH_PREFIX%%FILE_PATH%" ^| findstr !FINDSTR_FIRST_FILTER_CMD_LINE!
)

if %FLAG_F1_LINE_NUMBER_FILTER% NEQ 0 set CMD_LINE=!CMD_LINE! ^| findstr /N /R /C:".*"
if not "!FINDSTR_LINES_FILTER_CMD_LINE!" == "" set CMD_LINE=!CMD_LINE! ^| findstr !FINDSTR_LINES_FILTER_CMD_LINE!

rem echo !CMD_LINE! >&2
(
  endlocal
  rem to avoid ! character truncation
  setlocal DisableDelayedExpansion
  if %OUTPUT_HAS_NUMBER_PREFIX% NEQ 0 (
    if %FLAG_PRINT_LINE_NUMBER_PREFIX% NEQ 0 (
      %CMD_LINE% 2>nul
    ) else ( 
      for /F "usebackq eol= tokens=1,* delims=:" %%i in (`^(%CMD_LINE: | findstr = ^| findstr %^) 2^>nul`) do echo.%%j
    )
  ) else (
    %CMD_LINE% 2>nul
  )
)

exit /b 0
@echo关闭
rem说明:
通过findstr从文本/二进制文件提取字符串行的rem脚本
rem公用设施模式和/或线号。
rem命令参数:
rem%1-可选标志:
rem-n-为文件中找到的每个字符串打印行号前缀“:”。
rem默认情况下,行号前缀不打印。
rem-f1-按行号筛选%4..%N筛选模式之后的字符串。
默认情况下,rem根据文件中的行号进行过滤。
rem-pe-将输入文件视为可移植的可执行文件
rem(strings.exe必须存在)。
rem默认情况下,该文件被视为文本文件。
rem%1-包含要提取的文件的目录的路径。
rem%2-带字符串的文本/二进制文件的相对路径。
rem%3-以字符分隔的行号集,用于打印字符串。
rem默认情况下,这些行号是
rem文件,不是来自筛选输出。如果要指向行号
rem在%4..%N过滤器模式之后,则必须使用-f1标志。
rem如果为空,则视为“所有字符串”。
rem%4..%N-第一个筛选器中findstr命令行的参数。
rem如果为空,则视为/R/C:“*”,表示“任何字符串”。
rem警告:
rem在%4..%N个参数中不使用/N标志,而是使用script-N标志
带行号前缀的rem打印字符串。
rem示例:
rem 1.调用print_file_string.bat-n.example.txt 1:20:10:30/R/C:“*”
rem打印example.txt文件中按行号排序的1、10、20、30行
rem并打印它们,带有行号前缀:
雷姆
rem 2.调用print_file_string.bat.example.txt 100/R/C:“*”
rem打印example.txt文件的第100个字符串,然后不带行地打印它