0

以下のスクリプトは、token# 1 フィールドが出現するたびに出力を提供しますが、さらに 2 つの条件を追加する必要があります。

を。ファイルに何百万ものレコードがあるため、出力が複数の場合にのみ提供する必要があります。

b. 複数の文字列がある場合。つまり、行内のキー フィールドの組み合わせは、ファイル内の重複をすべての行にわたってチェックする必要があります。

@ECHO OFF

SETLOCAL enabledelayedexpansion
FOR %%c IN ($ #) DO FOR /f "delims==" %%i IN ('set %%c 2^>nul') DO
"SET %%i="

SET /a count=0

FOR /f "tokens=1delims=|" %%i IN (fscif.txt) DO (
 SET /a count+=1

 IF DEFINED $%%i (SET "$%%i=!$%%i! & !count!") ELSE (SET "$%%i=!count!")
  SET /a #%%i+=1 )

 FOR /f "tokens=1*delims=$=" %%i IN ('set $ 2^>nul') DO (  ECHO %%i;!#%%i! times;line no %%j 
)

例: 元のファイル (トークン 1 と 3 がキー フィールドであることを考慮)

123|12|ジャック

124|23|ジョン

123|14|ジャック

125|15|サム

125|66|サム

125|66|サム

出力ファイル:

123|ジャック;2 回;1 行目と 3 行目

125|Sam;3 回;4 行目、5 行目、6 行目

4

3 に答える 3

0

以下のバッチファイルは、あなたが望むことをします:

@echo off
setlocal EnableDelayedExpansion

rem Assemble "tokensValues" and "lastToken" variables from the parameters
set letters=0abcdefghijklmnopqrstuvwxyz
set tokensValues=%%!letters:~%1,1!
set lastToken=%1
:nextArg
   shift
   if "%1" equ "" goto endArgs
   set "tokensValues=!tokensValues!@%%!letters:~%1,1!"
   set lastToken=%1
   goto nextArg
:endArgs

rem Accumulate duplicated strings
set line=0
for /F "tokens=1-%lastToken% delims=|" %%a in (fscif.txt) do (
   set /A line+=1
   if not defined lines[%tokensValues%] (
      set lines[%tokensValues%]=!line!
   ) else (
      set "lines[%tokensValues%]=!lines[%tokensValues%]! & !line!"
   )
   set /A times[%tokensValues%]+=1
)

rem Show the result
for /F "tokens=2* delims=[]=" %%a in ('set lines[ 2^>NUL') do (
   if !times[%%a]! gtr 1 (
      set string=%%a
      set "string=!string:@=|!"
      echo !string!;!times[%%a]! times;line no %%b
   )
)

パラメータに必要なキー フィールドの数を指定する必要があります。たとえば、1 と 3 をキー フィールドと見なすには、次のようにします。

prog.bat 1 3

1 から 26 までの位置に最大 26 個のキー フィールドを指定できます。この制限は、最大 52 まで簡単に増やすことができます。

このバッチ ファイルは外部コマンドを使用せず、元のファイルに対して機能するため、高速に実行されるはずです。ファイルが大きい場合、sortまたはfindstrコマンドを実行すると時間がかかりすぎます (単純なであっcopyても)。

サンプルデータを実際のデータの代表として使用すると、lines変数は約2500〜3000行(つまり、同じキーフィールドが表示される異なる行の数)を保存する必要があり、合計環境スペースは64 MBであると思いますこのプログラム大きなファイルを処理できます。

于 2013-05-15T02:57:49.383 に答える
0
@ECHO OFF
SETLOCAL enabledelayedexpansion
:: Temporary filename
:tloop
SET "temppfx=%temp%\%random%"
IF EXIST "%temppfx%*" GOTO tloop
:: Hold that tempfile name...
ECHO.>"%temppfx%_"

:: a long string of spaces note the end-of-string quote -----here--v
SET "spaces=                                                       "
SET /a count=0

(
FOR /f "tokens=1,3 delims=|" %%a IN (fscif.txt) DO (
 SET /a count+=1
 SET "field1=%%a%spaces%"
 SET "field3=%%b%spaces%"
 SET "fieldc=%spaces%!count!"
 ECHO(!field1:~0,10!!field3:~0,12!^|!fieldc:~-8!^|!count!^|%%a^|%%b
)
)>"%temppfx%1"

:: Now report

SET "key=x"
SET /a count=0

(
FOR /f "tokens=1,3* delims=|" %%a IN ('sort "%temppfx%1" ') DO (
 IF "!key!"=="%%a" (
  SET "line=!line! %%b"
  SET /a count+=1
 ) ELSE (IF !count! neq 0 CALL :output
         SET key=%%a
     SET line=%%b
     SET "data=%%c"
         SET /a count=1
     )
)
CALL :output
)>report.txt

del "%temppfx%*"
GOTO :eof

:output
ECHO(!data!;%count% times;line nos %line: = ^& %

GOTO :eof

前に説明したように、何百万ものレコードがあると、環境スペースが不足する可能性があります。上に投稿したように、行番号のレポートが膨大になる可能性があるため、まだ使い果たしてしまう可能性があると思います-わかりません-あなたは実際のデータに精通しています.

基本的に、最初に行うことは、一時ファイルを作成することです。

入力ファイルで必要なトークンから始めます - 私は 1 と 3 に従いましたが、間違いなくもっとあるかもしれません - バウンドするボールに従ってください...

選択されたフィールドはパディングされます - テキスト フィールドの場合は右側、spaces変数を使用するカウント フィールドの場合は左側です。

次に、tempfile 出力が生成されます。最初のフィールドには 10 の最大長をランダムに選択し、2 番目のフィールドには 12 を選択しました。これら 2 つを組み合わせてkeyフィールドを作成します。先頭が埋められたカウント フィールドは 2 番目の列として出力されるため、SORTing の後、データはキー、次に行番号でグループ化されて表示されます。次に、関心のある残りの列が再現されます。

次に、データは次のfor/fループへの入力としてソートされます。トークン 1 (キー)、3 (生の行番号)、および「残り」 (パディングなしのキー) のみが重要です。

次に、一致するキーを数え、行番号を累積しline、キーが変更されたときに報告するだけです。最後のデータ項目を報告するには、最後の出力が 1 つ必要です。これで完了です。

于 2013-05-13T15:12:06.580 に答える