2012-07-27 71 views

Trả lời

9

Chắc chắn có thể, nhưng giống như hầu hết các tệp văn bản xử lý với hàng loạt, nó không phải là đẹp, và nó không phải là đặc biệt nhanh.

Giải pháp này bỏ qua trường hợp khi tìm kiếm trùng lặp và sắp xếp các dòng. Tên của tệp được chuyển thành đối số thứ nhất và duy nhất cho tập lệnh batch.

@echo off 
setlocal disableDelayedExpansion 
set "file=%~1" 
set "sorted=%file%.sorted" 
set "deduped=%file%.deduped" 
::Define a variable containing a linefeed character 
set LF=^ 


::The 2 blank lines above are critical, do not remove 
sort "%file%" >"%sorted%" 
>"%deduped%" (
    set "prev=" 
    for /f usebackq^ eol^=^%LF%%LF%^ delims^= %%A in ("%sorted%") do (
    set "ln=%%A" 
    setlocal enableDelayedExpansion 
    if /i "!ln!" neq "!prev!" (
     endlocal 
     (echo %%A) 
     set "prev=%%A" 
    ) else endlocal 
) 
) 
>nul move /y "%deduped%" "%file%" 
del "%sorted%" 

Giải pháp này phân biệt chữ hoa chữ thường và để các dòng theo thứ tự ban đầu (trừ các khóa trùng lặp). Một lần nữa tên của tập tin được truyền vào như đối số đầu tiên và duy nhất.

@echo off 
setlocal disableDelayedExpansion 
set "file=%~1" 
set "line=%file%.line" 
set "deduped=%file%.deduped" 
::Define a variable containing a linefeed character 
set LF=^ 


::The 2 blank lines above are critical, do not remove 
>"%deduped%" (
    for /f usebackq^ eol^=^%LF%%LF%^ delims^= %%A in ("%file%") do (
    set "ln=%%A" 
    setlocal enableDelayedExpansion 
    >"%line%" (echo !ln:\=\\!) 
    >nul findstr /xlg:"%line%" "%deduped%" || (echo !ln!) 
    endlocal 
) 
) 
>nul move /y "%deduped%" "%file%" 
2>nul del "%line%" 


EDIT

Cả hai giải pháp trên dòng trống dải. Tôi không nghĩ rằng các dòng trống đáng được bảo tồn khi nói về các giá trị riêng biệt.

Tôi đã sửa đổi cả hai giải pháp để tắt tùy chọn FOR/F "EOL" để tất cả các dòng không trống được giữ nguyên, bất kể ký tự thứ nhất là gì. Mã được sửa đổi đặt tùy chọn EOL thành ký tự linefeed.


giải pháp mới 2016/04/13: JSORT.BAT

Bạn có thể sử dụng của tôi JSORT.BAT hybrid JScript/batch utility để có hiệu quả sắp xếp và loại bỏ dòng trùng lặp với một lót đơn giản (cộng với một MOVE để ghi đè lên file gốc với kết quả cuối cùng). JSORT là tập lệnh thuần túy chạy tự nhiên trên bất kỳ máy Windows nào từ XP trở đi.

@jsort file.txt /u >file.txt.new 
@move /y file.txt.new file.txt >nul 
+0

Được chuyển thành chuỗi tìm kiếm finstr quá dài. –

+1

@Dreadedsemicolon - Có, tôi không nghĩ đến việc lựa chọn thứ 2 thất bại nếu bất kỳ dòng nào vượt quá chiều dài 511 (127 trên XP) do các giới hạn FINDSTR. – dbenham

3
set "file=%CD%\%1" 
sort "%file%">"%file%.sorted" 
del /q "%file%" 
FOR /F "tokens=*" %%A IN (%file%.sorted) DO (
SETLOCAL EnableDelayedExpansion 
if not [%%A]==[!LN!] (
set "ln=%%A" 
echo %%A>>"%file%" 
) 
) 
ENDLOCAL 
del /q "%file%.sorted" 

này nên làm việc giống hệt nhau. Ví dụ dbenham đó dường như quá cứng rắn đối với tôi, vì vậy, đã thử nghiệm giải pháp của riêng tôi. sử dụng ví dụ: filedup.cmd filename.ext

+0

Chỉ cần một FYI: Câu lệnh 'set' đầu tiên sẽ không hoạt động. Tôi đã thấy% CD% bị lỗi và/hoặc bị ghi đè nhiều lần! Bạn nên sử dụng nó thay vì 'set" file =% ~ dpnx1 "'. Các chữ cái trong% 1 được định nghĩa là: d = drive, p = path, n = filename (không có phần mở rộng), x = extension. Điều này làm việc cho đối số đầu tiên ngay cả khi bạn chỉ chuyển vào tên tệp (không có đường dẫn). – wasatchwizard

0

Đã gặp phải vấn đề này và phải tự khắc phục sự cố vì việc sử dụng là do nhu cầu của tôi. Tôi cần phải tìm URL trùng lặp và thứ tự các dòng có liên quan để nó cần được bảo tồn. Các dòng văn bản không được chứa bất kỳ dấu ngoặc kép nào, không nên dài và sắp xếp không thể được sử dụng.

Vì vậy, tôi đã làm điều này:

setlocal enabledelayedexpansion 
type nul>unique.txt 
for /F "tokens=*" %%i in (list.txt) do (
    find "%%i" unique.txt 1>nul 
    if !errorlevel! NEQ 0 (
     echo %%i>>unique.txt 
    ) 
) 

phụ: nếu văn bản có chứa dấu ngoặc kép thì FIND cần phải sử dụng một biến thiết lập lọc như mô tả trong bài viết này: Escape double quotes in parameter

Vì vậy, thay vì:

find "%%i" unique.txt 1>nul 

nó sẽ được nhiều hơn như:

set test=%%i 
set test=!test:"=""! 
find "!test!" unique.txt 1>nul 

Do đó, tìm sẽ giống như tìm "" "tệp" "nào và %% i sẽ không thay đổi.

1

Tôi đã sử dụng một "mảng" giả để thực hiện điều này

@echo off 
:: filter out all duplicate ip addresses 
REM you file would take place of %1 
set file=%1% 
if [%1]==[] goto :EOF 
setlocal EnableDelayedExpansion 
set size=0 
set cond=false 
set max=0 
for /F %%a IN ('type %file%') do ( 
     if [!size!]==[0] (
      set cond=true 
      set /a size="size+1" 
      set arr[!size!]=%%a 

    ) ELSE (
       call :inner 
       if [!cond!]==[true] (
        set /a size="size+1" 
        set arr[!size!]=%%a&& ECHO > NUL      
       ) 
    ) 
) 
break> %file% 
:: destroys old output 
for /L %%b in (1,1,!size!) do echo !arr[%%b]!>> %file% 
endlocal 
goto :eof 
:inner 
for /L %%b in (1,1,!size!) do ( 
      if "%%a" neq "!arr[%%b]!" (set cond=true) ELSE (set cond=false&&goto :break)         
) 
:break 

việc sử dụng các nhãn cho các vòng lặp bên trong là một cái gì đó cụ thể để cmd.exe và là cách duy nhất tôi đã làm tổ thành công cho vòng bên trong nhau. Về cơ bản, điều này so sánh mỗi giá trị mới đang được chuyển như một dấu tách và nếu không có kết quả phù hợp thì chương trình sẽ thêm giá trị vào bộ nhớ. Khi nó được thực hiện nó sẽ phá hủy các nội dung tập tin mục tiêu và thay thế bằng các dây độc đáo

2

Các tập tin hàng loạt dưới đây làm những gì bạn muốn:

@echo off 
setlocal EnableDelayedExpansion 
set "prevLine=" 
for /F "delims=" %%a in (theFile.txt) do (
    if "%%a" neq "!prevLine!" (
     echo %%a 
     set "prevLine=%%a" 
    ) 
) 

Nếu bạn cần một phương pháp hiệu quả hơn, hãy thử Batch- này Tập lệnh lai JScript được phát triển dưới dạng bộ lọc , tương tự như chương trình Unix uniq. Lưu tiện ích mở rộng .bat, như uniq.bat:

@if (@CodeSection == @Batch) @then 

@CScript //nologo //E:JScript "%~F0" & goto :EOF 

@end 

var line, prevLine = ""; 
while (! WScript.Stdin.AtEndOfStream) { 
    line = WScript.Stdin.ReadLine(); 
    if (line != prevLine) { 
     WScript.Stdout.WriteLine(line); 
     prevLine = line; 
    } 
} 

Cả hai chương trình được sao chép từ this post.

2

Hàng loạt tinh khiết - 3 dòng hiệu quả.

@ECHO OFF 
SETLOCAL 
:: remove variables starting $ 
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a=" 

FOR /f "delims=" %%a IN (q34223624.txt) DO SET $%%a=Y 
(FOR /F "delims=$=" %%a In ('set $ 2^>Nul') DO ECHO %%a)>u:\resultfile.txt 

GOTO :EOF 

Làm việc vui vẻ nếu dữ liệu không chứa các ký tự có hàng loạt có độ nhạy.

"q34223624.txt" vì câu hỏi 34.223.624 chứa dữ liệu này

1.1.1.1 
1.1.1.1 
1.1.1.1 
1.2.1.2 
1.2.1.2 
1.2.1.2 
1.3.1.3 
1.3.1.3 
1.3.1.3 

mà nó hoạt động hoàn hảo.

Các vấn đề liên quan