3

是否可以同时遍历多个文件的行?我需要通过加入两个不同文件中的行来输出一个文件(并添加一些额外的单词)。

我知道 CMD 命令:

FOR %variable IN (set) DO command [command-parameters]

但是,如果您需要同时迭代两个文件,这将无济于事。更准确地说,我需要以下内容:

While the first file is not ended
   line1 <- READ a line from the first file
   line2 <- READ a line from the second file
   WRITE on a third file line1 + line2

我正在寻找一种方法来完成我之前在dos 批处理文件中描述的内容。谢谢!

4

4 回答 4

8

我知道 3 种基本技术,从中可以衍生出大量的混合体。

选项 1(这个选项与 wmz 解决方案非常相似)

使用 FOR /F 读取文件 1,并使用带有 SKIP 选项的第二个 FOR /F 读取文件 2。必须在 CALLed 子例程中读取文件 2,以便可以在不中断文件 1 循环的情况下中断循环。

限制:

  • 空行会导致行不同步。空白行包含在跳过计数中,但 FOR /F 不读取。
  • ;由于默认的 EOL 选项,不会读取以开头的行。如有必要,可以通过将 EOL 设置为换行符来解决此问题。请参阅如何:FOR /F 禁用 EOF 或使用引号作为分隔符
  • 行的最大长度限制为 8191 字节。

这个选项很慢,因为 CALL 并且因为第二个文件必须为每一行读取一次。

编辑 - 如果第二个文件提前结束,代码固定为仍然输出一行

@echo off
setlocal disableDelayedExpansion
set "file1=a.txt"
set "file2=b.txt"
set "out=out.txt"

set /a cnt=0
set "skip="

>"%out%" (
  for /f "usebackq delims=" %%A in ("%file1%") do (
    set "found="
    call :readFile2
    if not defined found (echo %%A - )
  )
)
type "%out%"
exit /b

:readFile2
for /f "usebackq %skip% delims=" %%B in ("%file2%") do (
  set found=1
  echo %%A - %%B"
  goto :break
)
:break
set /a cnt+=1
set "skip=skip=%cnt%"
exit /b


选项 2

此选项通过使用 FINDSTR 在每行前面加上行号和冒号来解决空行问题。FINDSTR 用于仅读取文件 2 中的第 n 行,因此无需跳出第二个循环。

限制:

  • 前导冒号将从行中删除。这个限制可以通过额外的代码来消除,但它会使它变得更复杂和更慢。
  • 行的最大长度限制为 8191 字节。

此选项甚至比选项 1 慢

编辑 - 如果第二个文件提前结束,代码固定为仍然输出一行

@echo off
setlocal disableDelayedExpansion
set "file1=a.txt"
set "file2=b.txt"
set "out=out.txt"

>"%file2%.tmp" findstr /n "^" "%file2%"
>"%out%" (
  for /f "tokens=1* delims=:" %%A in ('findstr /n "^" "%file1%"') do (
    set "found="
    for /f "tokens=1* delims=:" %%a in ('findstr "^%%A:" "%file2%.tmp"') do (
      set found=1
      echo %%B - %%b
    )
    if not defined found (echo %%B - )
  )
)
del "%file2%.tmp"
type "%out%"


选项 3

使用 SET /P 读取这两个文件。FIND 用于获取文件 1 中的行数,因为 SET /P 无法区分空行和文件结尾之间的区别。

此选项消除了许多限制和复杂性,但引入了其自身的限制。

限制:

  • 行必须使用<CR><LF>. Unix 风格<LF>行不通。
  • 行限制为 1021 字节
  • 从每一行中去除尾随控制字符。

这个选项是迄今为止最快的。只要限制是可以接受的,它是优选的。

@echo off
setlocal enableDelayedExpansion
set "file1=a.txt"
set "file2=b.txt"
set "out=out.txt"

for /f %%N in ('type "%file1%"^|find /c /v ""') do set "cnt=%%N"
>"%out%" 9<"%file1%" <"%file2%" (
  for /l %%N in (1 1 %cnt%) do (
    set "ln1="
    set "ln2="
    <&9 set /p "ln1="
    set /p "ln2="
    echo !ln1! - !ln2!
  )
)
type "%out%"
于 2012-08-23T23:05:00.407 回答
2

现在我必须交付:-)

@echo off
setlocal disabledelayedexpansion
set count=0
for /f "delims=" %%F in (outer.txt) do (
  set fline=%%F
  call :inner %%count%%
  call echo %%fline%%
  set /a count+=1  

)
goto :eof

:inner
if %1 neq 0 set skipline=skip=%1 
  for /f "%skipline% delims=" %%S  in (inner.txt) do (
    set fline=%%F%%S
    goto :eof
  )

请注意,某些类型的输入可能会失败,例如。当行包含&或其他一些由 shell 特殊处理的字符时

于 2012-08-23T18:01:09.733 回答
0

附加文件内容:

echo FOO > foo.txt
echo BAR > bar.txt
type foo.txt > both.txt
echo "Both" >> both.txt
type bar.txt >> both.txt
于 2012-08-23T09:52:14.487 回答
0

我必须为 2 个字符串执行此操作(可能对其他人有用)

@echo off
setlocal enableextensions enabledelayedexpansion

set string1=token1,token2,token3
set string2=2ndtoken1,2ndtoken2,2ndtoken3

for %%A in (%string1%) do (
    echo From String1: %%A

    set str2=
    for %%S in (!string2!) do (
        if not defined str2 (
            set str2=%%S

            echo !str2!%>tempfile.txt
            FOR %%? IN (tempfile.txt) DO ( SET /A strlength=%%~z? - 1 )

            REM echo StrLen=!strlength!
            echo From String2: !str2!

            call set string2=%%string2:~!strlength!%%
            REM echo String2: !string2!
        )
    )
)
于 2016-04-13T14:50:25.373 回答