我正在开发一个需要创建某些资源的项目,同时创建资源我也会在文件中写入,以便在发生错误时回滚该创建过程。 但是这里有一个问题,资源必须以与创建它们相反的方式删除,所以当我写回滚文件时这样:
delete R1
delete R2
..
..
delete RN
我想按顺序删除资源 - >
delete RN
delete RN-1
....
...
delete R1
有没有办法在Windows批处理中做到这一点?
答案 0 :(得分:3)
使用批处理没有本机方式以相反的顺序读取文件。
但是,虽然不是最快的方法,但可以解决正常顺序读取文件,为每行添加填充数字,按相反顺序对列表进行排序,拆分行以分隔数字然后处理列表< / p>
@echo off
setlocal enableextensions disabledelayedexpansion
set "file=data.txt"
for /f "tokens=1,* delims=¬" %%a in ('
cmd /v:off /e /q /c"set "counter^=10000000" & for /f usebackq^ delims^=^ eol^= %%c in ("%file%") do (set /a "counter+^=1" & echo(¬%%c)"
^| sort /r
') do (
echo %%b
)
工作原理:
对于输入文件中的每一行,代码将输出一个数字前缀和一行,并带有分隔符(¬
),以便以后能够分隔这两个元素。
稍后将对数据进行排序,我们需要前缀具有统一的长度。因此我们在10000000
中初始化计数器并增加它,以便所有行中的前缀具有相同的长度(注意:如果您的文件有超过99999999行,请,请不要使用此方法)
要更改计数器,我们只需使用set /a "counter+=1"
,但要在循环中回显它,我们需要延迟扩展,但这可能会导致从文件中获取的数据出现问题(我不知道是否它可以包含!
个字符)。
我们可以启用/禁用延迟扩展来处理它,但由于这对于每一行都是必需的,因此会有性能损失。要解决此问题,代码将在单独的cmd
实例中执行。
为什么要单独的实例?此单独实例中的代码不是在批处理上下文中执行,而是在命令行上下文中执行。在命令行上下文中,set /a
命令回应了计算结果,因此我们不需要这样做,并且延迟扩展问题消失了。我们只计算新的计数器(得到回声),并回显分隔符和从输入文件中读取的行。所以我们有以下代码
set "counter=10000000"
for /f usebackq^ delims^=^ eol^= %%c in ("%file%") do (
set /a "counter+=1"
echo(¬%%c
)
它被编写为连接命令并作为参数传递给cmd
实例(注意:^
用于转义有问题的字符),这是用echo off
执行的({{ 1}}),已启用扩展程序(/q
)并禁用延迟扩展(/e
)
/v:off
这将生成前缀输出。现在,要按相反顺序排序,输出将通过管道传送到cmd /v:off /e /q /c"set "counter^=10000000" & for /f usebackq^ delims^=^ eol^= %%c in ("%file%") do (set /a "counter+^=1" & echo(¬%%c)"
命令。
sort /r
由于需要处理管道(在示例中我们只有cmd /c"..." | sort /r
到控制台的行),整个管道在echo
内执行(更多for /f %%a
转义字符)。
^
此 for /f "tokens=1,* delims=¬" %%a in ('
cmd /c"..." ^| sort /r
') do ....
命令表示for
字符将用作分隔符来标记输入行(管道执行的结果),并且我们要检索第一个标记(数字前缀,不会被使用,但需要被包括在内)¬
和%%a
中的其余部分(无需额外拆分)。
因此,最后,%%b
的{{1}}子句中的代码将以相反的顺序对输入文件中的每一行执行,并且行存储在{{1}中}。
答案 1 :(得分:0)
这会反转文件中的文本行。
<强>交换强>
filter swap
反转文件中的行,使顶行成为底线。
示例强>
cscript //nologo filter.vbs swap <"%systemroot%\win.ini"
来自https://skydrive.live.com/redir?resid=E2F0CE17A268A4FA!121的Filter.vbs - 19个用于处理文件中行的vbs程序。它包含一个批处理文件,可以轻松使用它。
Set Arg = WScript.Arguments
set WshShell = createObject("Wscript.Shell")
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
Dim LineCount
Set rs = CreateObject("ADODB.Recordset")
With rs
.Fields.Append "LineNumber", 4
.Fields.Append "Txt", 201, 5000
.Open
LineCount = 0
Do Until Inp.AtEndOfStream
LineCount = LineCount + 1
.AddNew
.Fields("LineNumber").value = LineCount
.Fields("Txt").value = Inp.readline
.UpDate
Loop
.Sort = "LineNumber DESC"
Do While not .EOF
Outp.writeline .Fields("Txt").Value
.MoveNext
Loop
End With