假设我们将以下代码段与文本文件sample.txt
重定向到STDIN
:
@echo off
< "sample.txt" (
set /P "ONE="
set /P "TWO="
findstr /R "^"
)
echo %ONE%, %TWO%
...以及相关文本文件sample.txt
的内容:
first
second
third
fourth
控制台上返回的输出将是这个,这正是我所期望的(first
消耗了行second
和set /P
,因此findstr
收到了并处理其余的行):
third fourth first, second
findstr /R "^"
替换为sort /R
时,会产生相同的输出。
但是,在findstr
或find /V ""
替换more
命令行时,输出将为:
first second third fourth first, second
虽然set /P
已经消耗了最后一行输出行证明的行first
和second
,但find
和more
仍然会收到整个重定向数据。
为什么会这样,导致这种行为的原因是什么?有没有办法强制find
或more
仅接收尚未被前面的命令处理过的剩余重定向数据?
(将输出数据STDOUT
重定向到文本文件时的行为相同。同样,在cmd
直接执行类似于上述批处理代码的命令行时,没有任何更改。)
答案 0 :(得分:1)
为什么有些命令会处理已被其他命令消耗的重定向STDIN数据行?
因为一些命令/程序倒带stdin。你可以试试这个:
@echo off
< "sample.txt" (
set /P "ONE="
set /P "TWO="
more +2
)
echo %ONE%, %TWO%
结果:
third
fourth
first, second
more +2
会跳过文件的前两行。
答案 1 :(得分:1)
好吧,关于命令为何以其行为方式运行的问题的即时解答位于Aacini的comment中:»“因为这样的命令是以这种方式编写的”。
无论如何,一段时间之后,我想收集我的发现,并最终提出我最近发现的新解决方法。
只有少数命令似乎不重置数据指针,并且每个命令都有其优缺点:
在问题中已经证明了使用findstr
返回剩余数据的用法。当重定向的输入数据没有通过最后的换行符终止时,findstr
可能会挂起问题:What are the undocumented features and limitations of the Windows FINDSTR command?
pause
不会重置数据指针(这实际上就是我想要在此处提到它的原因),而与数据是来自输入重定向还是来自管道无关,< strong>但是,不幸的是,它没有提供任何消耗的字符。
set /P
适用于读取长度不超过1 KB的单行,因此,要返回其余重定向数据,您将需要某种循环:
@echo off
rem // Count total number of available lines in advance:
for /F %%C in ('^< "sample.txt" find /C /V ""') do set "COUNT=%%C"
< "sample.txt" (
set /P "ONE="
set /P "TWO="
rem /* Loop here to return the rest; `3` is `1 + 2`, where `2`
rem is the hard-coded number of lines already handled; you can
rem just use `1` here, which will cause read attempty beyond
rem the end of data, causing empty lines to be returned: */
for /L %%N in (3,1,%COUNT%) do (
rem // Replace `&&` by `&` to NOT skip empty lines:
set "LINE=" & set /P "LINE=" && call echo(%%LINE%%
)
)
echo %ONE%, %TWO%
请注意,set /P
不能在管道内使用:Piping into SET /P fails due to uninitialised data pointer?
最后,sort
可用于返回余数。为防止其使文本行混乱,请使用字符位置选项/+n
并将n
设置为超出实际行长的数字:
@echo off
set "ONE="
set "TWO="
< "sample.txt" (
set /P "ONE="
set /P "TWO="
rem /* `sort` with the sort position set beyond the lines of text seems to
rem simply revert the current sort order; another reversion restores the
rem original sort order; I set the sort position just beyond the maximum
rem record or line length, which I set to the greatest possible value: */
sort /+65536 /REC 65535 | sort /+65536 /REC 65535
)
echo %ONE%, %TWO%
我将记录或行长(/REC
)设置为最大可能值,因为它默认为4096
。请注意,如果您指定的值较小,则最小值实际上为128
。另外请注意,换行符也算在内。