如何在使用CR但不使用LF的文本文件上使用FIND命令



我不知道是否真的可以这样做,但我有一个文本文件,其中包含一些行,这些行只使用ascii Carriage Return(CR)字符,后面没有换行符(LF)字符。

我的问题是,我试图使用FIND命令在文件中搜索字符串,但我无法让它返回任何带有CR的行(很明显,它确实返回CR+LF行)。

有没有什么方法可以使用本机批处理命令搜索这些行?

我已经对FINDSTR进行了详尽的测试,我知道如果它只有<CR>而没有<LF>,它会将整个文件视为一行。

我还没有用FIND做过同样级别的测试,但我怀疑它会有同样的问题。但我现在不能肯定。


编辑1

我已经确认(无论如何在Vista上),FIND严格在<LF>之后换行,无论之前是否有<CR><CR>字符只是作为另一个字符处理。

搜索嵌入了<CR>的行应该不会有任何问题。问题将是输出在屏幕上的外观。此外,多条逻辑线将被视为一条线(以<CR>"结束"的逻辑线)。

我创建了一个test.txt文件,其结构如下

1<CR><LF>
2<CR><LF>
3<CR>4<CR>5<CR><LF>
6<CR><LF>
7<CR><LF>

然后用FIND对付

FIND "2" <test.txt
-> 2
FIND "3" <test.txt
-> 5
FIND "4" <test.txt
-> 5
FIND "5" <test.txt
-> 5
FIND "6" <test.txt
-> 6

搜索3和4时,输出看起来很奇怪,但实际上是正确的。这是因为3、4和5都在同一条线上。FIND打印出整行,但回车会导致3被4覆盖,4被5覆盖。如果我执行FIND "3" <test.txt >out.txt,它将生成一个长度为7字节的文件。

如果你使用FINDSTR,你会得到基本相同的结果。

不能强制FIND(或FINDSTR)在单个<CR>处换行。但是,您可以使用以下简单的混合脚本对文件进行预处理,将单独的<CR>字符转换为Windows标准的行终止符。脚本将要转换的文件名作为第一个也是唯一的参数。

转换的肉是用JScript完成的,其余的是用batch完成的。使用混合可能很愚蠢——整个过程本来可以用JScript(或VBScript)完成,但混合很有趣。您还可以根据需要轻松添加其他批处理命令。例如,可以在MOVE之后、EXIT/B之前添加FIND命令。

警告-脚本重写了原始文本文件。如果希望修改后的版本是一个单独的文件,请删除MOVE命令。

@if (@x)==(@y) @end /* harmless valid code for both batch and Jscript
::********* Batch Part **************************************************
:: This batch script calls the JScript below to normalize the end-of-line
:: for the contents of the file name passed in as parameter 1.
:: It redirects JScript to read its input from the file, and writes the
:: output to a new file. The batch script than moves the new file to 
:: replace the original.
::
:: You could put your FIND command after the MOVE and before the EXIT /B.
::
@echo off
<%1 cscript //e:jscript /nologo "%~f0" >"%~1.new"
move "%~1.new" "%~1" >nul
exit /b
*********** JScript Part **************************************
* This little script reads stdin, normalizes the end-of-line,
* and writes the result to stdout
*
* <CR><LF> -> no change
* <LF> without preceding <CR> -> <CR><LF>
* <CR> without following <LF> -> <CR><LF>
*/
while (!WScript.StdIn.AtEndOfStream) {
  WScript.StdOut.WriteLine(WScript.StdIn.ReadLine().replace( /r/g, "rn" ) );
}

编辑2

我刚刚意识到,如果我只是稍微修改上面的脚本,就有一种完全无损的方法来搜索由<CR>终止的"行"。除了做出必要的修改外,我还删除了这些评论。

脚本现在有两个参数:"searchString"、"fileName"

@if (@x)==(@y) @end /* harmless valid code for both batch and Jscript
::********* Batch Part **********************************************
@echo off
<%2 cscript //e:jscript /nologo "%~f0" | find "%~1"
exit /b
*********** JScript Part *******************************************/
while (!WScript.StdIn.AtEndOfStream) {
  WScript.StdOut.WriteLine(WScript.StdIn.ReadLine().replace( /r/g, "rn" ) );
}

最新更新