2012-05-07 10 views
0

fileA.txt内のすべての行を含むfileC.txtを作成するバッチを作成しようとしていますが、文字列を含む行を除いて例えばLバッチ:(fileA.txtからfileB.txtを差し引いた)結果からfileC.txtを作成

が含まれている場合

foreach(line L in fileA.txt) 
    excluded = false 
    foreach(string str in fileB.txt) 
      if L contains str 
       exclude = true 
    if !excluded 
      add L to fileC.txt 

fileA.txt::!は

疑似:fileB.txtの行で(すべての)

this\here\is\a\line.wav 
and\this\is\another.wav 
i\am\a\chocolate.wav 
peanut\butter\jelly\time.wav 

fileB.txt:(それらが除外される)

another.wav 
time.wav 

fileC.txt:(結果を望んでいた)

this\here\is\a\line.wav 
i\am\a\chocolate.wav 

私がいじってきました私はちょうどそれを一緒に困惑することはできません..任意のヘルプやポインタが大いに感謝!

乾杯! /Fredde

答えて

2

答えは、このシンプルでなければなりません:

findstr /lvg:"fileB.txt" "fileA.txt" >fileC.txt 

そして、あなたの例で、上記のは、正しい結果が得られません。

しかし、複数の大文字と小文字を区別するリテラル検索文字列を使用すると、信頼性の低い厄介なFINDSTRバグがあります。 Why doesn't this FINDSTR example with multiple literal search strings find a match?とそれに付随する答えを参照してください。文書化されていないFINDSTR機能とバグの「完全な」リストについては、What are the undocumented features and limitations of the Windows FINDSTR command?を参照してください。

したがって、上記の単純なコードは、ファイルの内容によっては失敗する可能性があります。大文字と小文字を区別しない検索を使用することで逃れることができれば、その解決法は簡単です。

findstr /livg:"fileB.txt" "fileA.txt" >fileC.txt 

編集:fileB.txtが\\または\"が含まれている場合は、上記のどちらのバージョンが失敗します。正しく動作するためには、これらの文字列は\\\\\"

のようにエスケープする必要がありますしかし、あなたは大文字と小文字を区別した検索を使用する必要がある場合は、その後、簡単な解決策はありません。純粋なバッチソリューションの最良の賭けは、/ R正規表現オプションを使うことかもしれません。しかし、文字列が正しいリテラル検索を行うように、すべてのregexメタ文字がエスケープされたfileB.txtの変更バージョンを作成する必要があります。それはそれ自体のミニプロジェクトです。

おそらく大文字小文字を区別する解決策として、Windows用のgrepやsedのようなサードパーティのツールを入手することをお勧めします。

編集:ここで私はあなたの質問で提案されているロジックのようなものをやってに見えた

証拠弾丸がほとんどである合理的に実行する純粋なバッチソリューションです。しかし、バッチを使用してファイル内のすべての行を読み取るのは比較的遅いです。このソリューションは、除外ファイルを1行ずつ読み込みます。 FINDSTRを使用して、 "fileA.txt"の行を検索文字列ごとに1回ずつ繰り返し読み込みます。これは、バッチファイルのはるかに高速なアルゴリズムです。

ファイルを読み取る伝統的な方法は、FOR/Fループを使用することですが、高速なSET/Pを使用するもう1つの手法があり、遅延展開で安全に使用できます。この方法の唯一の制限は以下のとおりです。

  • それはWindowsの標準があるように、各ラインが<CR><LF>で終了する必要がありますライン
  • あたり1021バイトに制限されているライン
  • から制御文字を末尾のストリップ。それは彼らが/ Cオプションで使用されているときに、検索文字列は、各\"\\\"としてエスケープされている必要があり<LF>

で終了し、UNIXスタイルのラインでは動作しません。

@echo off 
setlocal enableDelayedExpansion 
copy fileA.txt fileC.txt >nul 
for /f %%N in ('find /c /v "" ^<fileB.txt') do set len=%%N 
<fileB.txt (
    for /l %%N in (1 1 !len!) do (
    set "ln=" 
    set /p "ln=" 
    if defined ln (
     set "ln=!ln:\=\\!" 
     set ln=!ln:"=\"! 
     move /y fileC.txt temp.txt >nul 
     findstr /lv /c:"!ln!" temp.txt >fileC.txt 
    ) 
) 
) 
del temp.txt 
type fileC.txt 
+0

非常に精巧で満足のいく回答です!あなたの最初の解決策が私の場合には十分であったにもかかわらず、私はあなたのポスト全体を読むことをとても楽しんだ!もしできれば、私はそれをアップヴォートするだろう! 私はあなたの前にひれ伏します。 ありがとう:) * punの意図 – happytrooper

関連する問題