我尝试使用CMD或VBS删除包含txt文件中关键字的某些行。
我已阅读this,但情况并不相同。我想删除一系列行。
原始文本文件:
ABCDEFGXXX
ABCD
A
AE
AXXXLKGUSP
0000ASD
ASD
已处理的文字文件:
0000ASD
ASD
我想删除包含' XXX'的第一个实例的行范围和第二个。这个' XXX'只有两个例子。两个实例之间的行数是随机的,并且可能存在两个实例在同一行中的情况。 4个零也出现在' XXX'的第2个实例的行之后。请注意,它可能包含以下字符,因此如果您尝试处理,它可能会窒息。
---------------------编辑08/04/2015 7:41 PM ---------------- ------------------- " XXX"全部大写......文本文件可能包含下面的字符..但它在记事本中显示一行。 IDK他们是什么
PK
¨‘G_t¥0 8ˆ XXXç¸[~-ÄWÀ¨Ì’gÝ
答案 0 :(得分:1)
假设您已经提到VBS表示可以使用非纯语法语法解决方案,这里有一个PowerShell单行程序,您可以从.bat调用。
它以default
系统编码读取文本文件,其他有用的值为UTF8
和Unicode
。
在2秒内处理100MB文件。
@echo off
set "string=XXX"
set "infile=input file.txt"
set "outfile=output file.txt"
set "encoding=default"
powershell -ExecutionPolicy bypass -c "$txt=(get-content '%infile%' -raw -encoding default); $i=$txt.indexof('%string%'); if($i -ge 0) { $j=$txt.indexof('%string%',$i+'%string%'.length); if($j -ge 0) {$k=$txt.indexof(\"`n\",$j); if($k -ge $j){$txt2=$txt.substring($k)} else {$txt2=''} $txt.substring(0,[math]::max(0,$txt.lastindexof(\"`n\",$i))) + $txt2 | out-file '%outfile%' -encoding %encoding%}}"
pause
-ExecutionPolicy bypass
以允许在非管理员用户帐户上执行powershell。答案 1 :(得分:1)
这对于JREPL.BAT来说非常简单 - 一个基于纯脚本的实用程序(混合JScript /批处理),可以在XP以后的任何Windows机器上本机运行。关键特性是它支持多行正则表达式搜索和替换。
以下内容将覆盖原始文件:
jrepl "^.*?XXX[\s\S]*XXX.*\n?" "" /m /f "test.txt" /o -
如果您要创建新文件,只需为-
选项指定文件名而不是/O
:
jrepl "^.*?XXX[\s\S]*XXX.*\n?" "" /m /f "input.txt" /o "output.txt"
或者您可以完全省略/O
选项并将结果打印到屏幕(标准输出)
jrepl "^.*?XXX[\s\S]*XXX.*\n?" "" /m /f "input.txt"
如果您将命令放在批处理脚本中,请使用call jrepl ...
。
编辑:这是一个纯批处理解决方案。通常我放弃使用批处理进行文本处理,因为强大的解决方案需要过多的精神错乱。下面的代码非常强大和优化,但即使如此,仍然有以下限制:
*
开头,且不能包含=
,!
或"
可能还有一些我错过了。
但代码确实保留了空行,并且不会阻塞内容中的!
。 (处理这些可能性是造成复杂性的原因)
@echo off
setlocal disableDelayedExpansion
set "in=input.txt"
set "out=output.txt"
set "find=XXX"
set "cnt=0"
>"%out%" (
for /f "delims=" %%A in ('findstr /n "^" "%in%"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
if defined ln if !cnt! equ 0 (
set "test=!ln:*%find%=!"
if !test! neq !ln! set "cnt=1"
) else set "test=!ln!"
if !cnt! neq 1 echo(!ln!
if defined test if !cnt! neq 2 if "!test:%find%=!" neq "!test!" set "cnt=2"
for %%N in (!cnt!) do endlocal&set "cnt=%%N"
)
)
答案 2 :(得分:1)
这是一个纯粹的CMD实现:
@echo off
rem DEFINITIONS:
set "KEYWD=XXX"
set "INFILE=original.txt"
set "OUTFILE=modified.txt"
setlocal EnableExtensions EnableDelayedExpansion
rem GET_LINE_NUMBERS:
set "NUMONE="
set "NUMTWO="
for /F %%F in ('findstr /N /L /C:"%KEYWD%" "%INFILE%"') do (
for /F "delims=:" %%N in ("%%F") do (
if not defined NUMONE (
set "NUMONE=%%N"
) else (
set "NUMTWO=%%N"
)
)
)
if not defined NUMTWO set "NUMTWO=%NUMONE%"
rem RETURN_BEFORE_BLOCK:
set /A "COUNT=0"
rem.> "%OUTFILE%"
for /F "delims=" %%L in ('findstr /N /R "^" "%INFILE%"') do (
set /A "COUNT+=1"
if !COUNT! geq !NUMONE! (
goto :NEXT
) else (
setlocal DisableDelayedExpansion
set "LINE=%%L"
setlocal EnableDelayedExpansion
echo(!LINE:*:=!
endlocal
endlocal
) >> "%OUTFILE%"
)
rem RETURN_AFTER_BLOCK:
:NEXT
if defined NUMTWO set "SKIP=skip=!NUMTWO!"
for /F "%SKIP% delims=" %%L in ('findstr /N /R "^" "%INFILE%"') do (
setlocal DisableDelayedExpansion
set "LINE=%%L"
setlocal EnableDelayedExpansion
echo(!LINE:*:=!
endlocal
endlocal
) >> "%OUTFILE%"
endlocal
代码由四部分组成(请参阅备注rem
):
NUMONE
和NUMTWO
中;如果只找到一行(a)匹配,NUMTWO
设置为NUMONE
;如果未找到匹配项,则两个变量都保持为空; goto
打破任何正在进行的for
循环上下文的事实; for /F
选项参数skip
是动态构建的; 答案 3 :(得分:0)
这是另一个JScript / Batch混合解决方案。
假设文本文件位于data.txt
中,我们可以调用替换脚本:
cscript //nologo j.js .*XXX.*\n[\s\S]*?.*\n*XXX.* "" < data.txt
j.js
是使用Microsoft JScript编写的支持脚本:
var txt = WScript.StdIn.ReadAll();
var pattern = new RegExp( WScript.Arguments.Item(0), "g" );
var newvalue = WScript.Arguments.Item(1);
txt = txt.replace( pattern, newvalue );
WScript.StdOut.Write( txt );
j.js
脚本的高尔夫优化版本为:
WScript.StdOut.Write(WScript.StdIn.ReadAll().replace(new RegExp(WScript.Arguments.Item(0),"g"),WScript.Arguments.Item(1)));
通常,j.js
的用法是:
cscript //nologo j.js pattern_regular_expression new_value < input.dat > output.dat
input.dat
指的是输入文本/数据文件。如果省略< input.dat
,则输入将从用户输入中获取。 output.dat
指的是输出文本/数据文件。如果省略> output.dat
,则输出将显示在控制台上。