私は 3 つの基本的なテクニックを知っており、そこから多数のハイブリッドを導き出すことができます。
オプション 1 (このオプションは wmz ソリューションに非常に似ています)
FOR /F でファイル 1 を読み取り、2 番目の FOR /F で SKIP オプションを指定してファイル 2 を読み取ります。ファイル 2 は、ファイル 1 のループを中断せずにループを中断できるように、呼び出されたサブルーチンで読み取る必要があります。
制限:
このオプションは、CALL と、2 番目のファイルを行ごとに 1 回読み取る必要があるため、低速です。
編集 - 2 番目のファイルが早期に終了した場合でも行を出力するように修正されたコード
@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 番目の行のみを読み取るために使用されるため、2 番目のループから抜け出す必要はありません。
制限:
- 先頭のコロンは行から削除されます。この制限は追加のコードで解消できますが、より複雑で遅くなります。
- 行の最大長は 8191 バイトに制限されています。
このオプションは、オプション 1 よりもさらに遅くなります
編集 - 2 番目のファイルが早期に終了した場合でも行を出力するように修正されたコード
@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 を使用して両方のファイルを読み取ります。SET /P は空白行とファイルの終わりを区別できないため、FIND を使用してファイル 1 の行数を取得します。
このオプションは、多くの制限と複雑さを取り除きますが、独自の制限を導入します。
制限:
- 行には、Windows スタイルの行末記号
<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%"