File Windows批处理:同时迭代多个文件行

File Windows批处理:同时迭代多个文件行,file,cmd,batch-file,File,Cmd,Batch File,是否可以同时迭代多个文件的行?我需要通过将两个不同文件中的行连接起来(并添加一些额外的单词)来输出一个文件 我知道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

是否可以同时迭代多个文件的行?我需要通过将两个不同文件中的行连接起来(并添加一些额外的单词)来输出一个文件

我知道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
当第一个文件未结束时

第1行追加文件内容:

echo FOO > foo.txt
echo BAR > bar.txt
type foo.txt > both.txt
echo "Both" >> both.txt
type bar.txt >> both.txt

现在我必须交付:-)


请注意,对于某些类型的输入,它可能会失败,例如,当行包含
&
或shell专门处理的某些其他字符时

我知道有3种基本技术,可以从中派生出大量的混合字符

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

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

限制:

  • 空行将导致行不同步。空行包括在跳过计数中,但不由FOR/F读取
  • 开头的行。如有必要,可通过将下线设置为新行字符来解决此问题。看
  • 行的最大长度限制为8191字节
由于调用以及每行必须读取一次第二个文件,此选项速度较慢

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


选项2

此选项通过使用FUNSTRT将每行的前行加上冒号来解决空白行问题。FINDSTR只用于读取文件2中的第n行,因此无需中断第2个循环

限制:

  • 将从线路上去掉前导冒号。这个限制可以用额外的代码消除,但它会使它变得更复杂和更慢
  • 行的最大长度限制为8191字节
此选项甚至比选项1慢

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


选项3

使用SET/p读取这两个文件。“查找”用于获取文件1中的行数,因为SET/P无法区分空行和文件结尾之间的差异

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

限制:

  • 行必须使用Windows样式的
    行终止符。Unix样式
    将不起作用
  • 行限制为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%"
@echo关闭
setlocal enableDelayedExpansion
设置“file1=a.txt”
设置“file2=b.txt”
设置“out=out.txt”
对于('type“%file1%”中的/f%%N^ | find/c/v“”),请设置“cnt=%%N”

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


是否要交错内容?您可以使用嵌套的
for/f
来实现这一点。给我们更多的细节,这样我们可以提出一些建议。@wmz:我已经更新了我的问题。请看一看。谢谢。我喜欢第三种选择——这是一种我从未想过的聪明的阅读方式。效率/速度上的明显赢家。第一个文件上有一个小提示——第二个文件一结束,它就会停止回音。若第二个文件恰好小于,它将不会输出第一个文件行的其余部分。这就是为什么我最终使用了集合,而不是直接在
的内部循环
中回音(我在我的第一个版本中也这样做了)。@wmz-这一点很好,它也适用于选项2。我已经修复了选项1和选项2来处理行数较少的文件2。Noob问题:我正在尝试第三个选项,这正是我来这里想要的。但是我不想要
out.txt
,只想要
回音!ln1!-!液氮。我试图
设置“out=NUL”
,但根本没有输出。我猜这是完成这项工作的必要条件?或者仅仅是因为这个问题需要它,并且可以消除它?如果是,请告诉我。否则,我可以最终删除该文件。@laggingreflect-只需完全删除
>“%ou%”
,以及定义out的行和键入out文件的行。FOR/F选项将EOL设置为引号字符,并使用TOKENS=*将从每行删除前导空格和制表符。最好使用“DELIMS=”。如果担心前导分号,则需要将EOL设置为新行字符以有效禁用它。
@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
@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%"
@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%"
@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!
        )
    )
)