Пакетное: объединить текстовые файлы в столбцах - PullRequest
1 голос
/ 22 сентября 2011

Я пытаюсь объединить текстовые файлы (из которых первый столбец равен всем) в один файл. Тысячи из них, которые я приобретаю в своих экспериментах. Я использую 3 входных файла в качестве примера, чтобы проиллюстрировать, что я пытаюсь достичь:

1.txt     2.txt     3.txt
l1 a1     l1 b1     l1 c1
l2 a2     l2 b2     l2 c2
l3 a3     l3 b3     l3 c3

Таким образом, все входные файлы имеют первый общий столбец. Я хочу получить этот вывод:

out.txt
l1 a1 b1 c1
l2 a2 b2 c2
l3 a3 b3 c3

Попытка 1 из 3

:: hmm.bat=============================================
@echo off > hmm.txt & setLocal enableDELAYedeXpansion
echo AAAAAAAAAAaaaaaaaaaa............
pushd %*

for /f "tokens=1* delims= " %%a in (a1.txt) do (
>> hmm.txt echo. %%a hm
)

for %%j in (*.txt) do (
   echo. %%j yes? >> hmm.txt
   for /f "tokens=2* delims= " %%a in (%%j) do (
   >> hmm.txt echo. %%a
   )
)
popd
:: End_Of_Batch======================================

Этот пакетный файл извлекает нужные мне столбцы, но вместо этого все в отдельных столбцах, все данные в одном столбце. Мне не удалось получить вывод в отдельные столбцы.

Эта попытка (2 из 3) в конечном итоге даст то, что я хочу:

::=============================================
@echo off > tral.txt & setLocal enableDELAYedeXpansion

set N=
for /f "tokens=1* delims= " %%a in (a1.txt) do (
set /a N+=1 & call :sub1 %%a & set A!N!=!C!
)

set N=
for /f "tokens=* delims= " %%a in (a1.txt) do (
set /a N+=1 & call :sub1 %%a & set B!N!=!C!
)

set N=
for /f "tokens=* delims= " %%a in (a2.txt) do (
set /a N+=1 & call :sub1 %%a & set C!N!=!C!
)

set N=
for /f "tokens=* delims= " %%a in (a3.txt) do (
set /a N+=1 & call :sub1 %%a & set D!N!=!C!
)

for /L %%a in (1 1 !N!) do (
>> tral.txt echo. !A%%a! !B%%a! !C%%a! !D%%a!
)
goto :eof

:sub1 set C to last token
:loop
if '%2' neq '' (
shift
goto :loop
)
set C=%1
goto :eof
::================================================

Однако, чтобы распространить это на многие (тысячи) файлов, мне нужно было бы повторить бит

set N=
for /f "tokens=* delims= " %%a in (a*.txt) do (
set /a N+=1 & call :sub1 %%a & set x!N!=!C!
)

Мааааааааные времена. Я попытался использовать цикл вместо:

Попытка 3 из 3

::=============================================
@echo off & setLocal enableDELAYedeXpansion
type nul > slow.txt

set N=
for /f "tokens=1* delims= " %%a in (a1.txt) do (
set /a N+=1 & call :sub1 %%a & set A!N!=!C!
)

for %%j in (*.txt) do (
set N=
for /f "tokens=* delims= " %%a in (%%j) do (
set /a N+=1 & call :sub1 %%a & set x!N!=!C!
)
)

for /L %%a in (1 1 !N!) do (
>> slow.txt echo. !A%%a! !x%%a!
)
goto :eof

:sub1 set C to last token
:loop
if '%2' neq '' (
shift
goto :loop
)
set C=%1
goto :eof
::=============================================

Я получаю первый столбец (который объединяет все файлы данных) и второй столбец самого последнего файла данных. Я не знаю, как обновить переменную x в! X %% a! для каждого файла, чтобы распечатать это в отдельном столбце.

В качестве альтернативы кто-нибудь знает, возможно ли выводить данные в конце выбранной строки в выходном файле? Затем я должен отобразить его до конца первой строки, что приведет к отображению всех данных в столбцах. Использование

set /P line1=< hmm.txt

, а затем

echo.%line1% %%a>>hmm.txt

не приводит к отражению в конце первой строки, а скорее в конце последней строки.

У кого-нибудь есть решение в любом случае?

Ответы [ 2 ]

1 голос
/ 23 сентября 2011

Я не думаю, что программирование на BAT подходит для того, что вы хотите достичь.Вы можете найти какое-то запутанное решение или в конечном итоге использовать сторонний инструмент для дополнения программирования на BAT (SED приходит мне в голову), если IMO только добавит еще одну проблему в уравнение, либо вынудит пользователя установить такой инструмент, либо усложнит вашеРаспространение и установка BAT с той же целью.

С другой стороны, решение вашей проблемы - очень простая задача для программирования на любом общем языке программирования.

Итак, я бы попробовал VB или javascript, которые доступны практически во всех установках Windows.Взгляните на это и начните ...

@set @junk=1 /*
@echo off
rem textcolumns text
cscript //nologo //E:jscript %0 %*
goto :eof
:allfiles
pushd %1
for /f %%a in ('dir /b /s *.txt') do
  call :coltxt %%a
)
goto :eof
:coltxt
cscript //nologo //E:jscript %*
goto :eof
*/


function openFile(fn) {
 var ForReading = 1, ForWriting = 2, ForAppending = 8;
 var TristateUseDefault = -2, TristateTrue = -1, TristateFalse = 0;
 var fso = new ActiveXObject("Scripting.FileSystemObject");
 // Create the file, and obtain a file object for the file.
 // fso.CreateTextFile(fn);
 var f = fso.GetFile(fn);
 // Open a text stream for input.
 ts = f.OpenAsTextStream(ForReading, TristateUseDefault);
 // Read from the text stream and display the results.
 return ts;
}


function removeFirstWord(s) {
  var p1=s.indexOf(" ");
  if (p1>0) {
    return s.substring(p1+1);
  } else {
    return new String();
  }
}

function getCol(ts) {
 var s;
 s = ts.ReadLine();
 s = removeFirstWord(s);
 return s;
}


// main 
x = WScript.Arguments;
fs = new Array(x.length);

for (var i=0; i<x.length; i++) {
 fs[i] = openFile(x(i));
}

while (!fs[0].AtEndOfStream) {
  var s = fs[0].ReadLine();
  for (var i=1; i<fs.length; i++) {
    s += getCol(fs[i]);
  }
  WScript.echo(s);
}

for (var i=0; i<fs.length; i++) {
  fs[i].close();
}
1 голос
/ 23 сентября 2011

Тем временем мне удалось найти решение (с большой помощью от других на http://www.computing.net/answers/programming/merge-files-in-column-output/26553.html).

Возможно, когда-нибудь кому-то еще будет полезно это тоже.

Сначала этосчитает файлы (nr файлов используется позже). Имена файлов без расширения перечислены в файле "list.dat".

@echo off 
SetLocal EnableDelayedExpansion
for /f  %%a in ('dir/b *.txt') do (
    set /a count+=1
    set /a count1=count-1
)
echo total is !count!
echo !count1!

rem empty contents of files
type nul > x.txt
type nul > y.txt
type nul > z.txt
type nul > list.dat

setlocal
set first=y
(
    for /f %%g in ('dir/b/a-d a*.txt') do (
        if defined first (
            set first=
            set/p=%%~ng <nul
        ) else (
            set/p=%%~ng <nul
        )
    )
)>>list.dat

for /f %%j in (list.dat) do (
    echo. %%j   
    for %%a in (%%j) do find /n /v "" < %%a.txt >> x.txt
)
sort x.txt /o x.txt

set "regex=^\[[0-9]\]"
:loop
findstr /r "%regex%" x.txt >> y.txt
if not errorlevel 1 (
    set "regex=^\[[0-9]%regex:~3%
    goto loop
)

set cnt=
set line=
for /f "delims=" %%a in (y.txt) do (
    set input=%%a
    set input=!input:*]=!
    set line=!line! !input!
    if "!cnt!"=="!count1!" (
        >> z.txt echo !line:~1!
        set line=
    )
    set /a cnt=^(cnt + 1^) %% !count!
)

type nul > zz.dat
for /F "delims=" %%i in (z.txt) do (
    set cnt=1
    set rrow=
    for %%j in (%%i) do (
        set /A cnt-=1
        if !cnt! equ 0 (set cnt=0 & set rrow=!rrow! %%j)
    )
    set cnt=2
    set row=
    for %%j in (%%i) do (
        set /A cnt-=1
        if !cnt! equ 0 (set cnt=2 & set row=!row! %%j)
    )
    set row=!row:~1!
    echo. !rrow! !row!>> zz.dat
)

del x.txt
del y.txt
pause
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...