- 我决定重新格式化我的问题,由于用户的意见(感谢所有)和新的知识,我已经得到了。我不会打开一个新的职位,因为主要问题仍然是相同的:*
如果某个程序(如CURL)生成的字符串没有LF
终止符,如何逐行动态处理这些字符串?
CURL产生每一行的时间间隔大约为1秒。我只需要从CURL输出中选择一些字段进行进一步处理(当前速度、下载的字节数、下载的百分比),所以我需要处理每一个新出现的行。但我不能,因为每一行都以CR
结尾。
在下载完成之前,FOR循环不会在CMD窗口中显示任何内容,其他用户向我解释了原因:
FOR /F "delims=" %%x in ('curl ... http://some_url 2^>^&1') do echo %%x
于是,我被迫放弃了FOR
:
curl ... http://some_url | string_handler.bat
使用JREPL动态地将CR
替换为CRLF
:
curl ... http://some_url 2>&1 | jrepl "\r([^\n])" "\r\n$1" /xseq
但是,这种解决方案在CURL完成后会产生空洞输出,而不是逐行输出,因为如果字符串没有LF
终止符,则PIPE就没有任何内容(感谢@Stephan)。也许有解决方案可以绕过PIPE行为?
为了解决这个问题,我做了一个简单的脚本-模拟CURL输出。这是倒计时计时器,它每1秒产生一行与CR
终止符,除了第一行和最后一行有CRLF
:
:: bears.bat
@echo off
setlocal enabledelayedexpansion
::Define LF variable containing a linefeed (0x0A)
(set LF=^
%=empty line%
)
::Get a CR character (0x0D)
for /F %%a in ('copy /Z "%~F0" NUL') do set "CR=%%a"
:: First argument is CountDown high level, default 4 sec
if "%1"=="" (set /a high=4) else (set /a high=%1)
echo Hello bears
for /l %%i in (%high%,-1,0) do (
if %%i gtr 0 (
<nul set /p="Counter: %%i!CR!"
) else (
<nul set /p="Counter: %%i!CR!!LF!"
)
:: Pause 1 sec
if %%i gtr 0 ping 127.0.0.1 -n 2 >nul
)
exit /b
2条答案
按热度按时间sshcrbum1#
如果你想把Mac的'CR'结尾行替换成Windows的'CRLF',我想这也是你所要求的,那么下面的方法应该可以实现:
快速说明:
For /F
命令在第一次出现“LF”时终止一行,如果前面是“CR ",则会删除该”CR“,但保留任何其他”CR“字符。如果展开包含”CR“的For
变量(在本例中为%%G
),则也会保留该”CR“。但是,如果展开环境变量%LineWithCR%
,所有的“CR”字符都将被删除。但是,为了扩展包含“CR”的环境变量,您需要使用延迟扩展,例如!LineWithCR!
。0mkxixxg2#
正如已经说过的,它不能用FOR /F循环来解决,因为它总是在开始循环之前等待完整的输出。
但它可以通过异步模式和两个线程来解决。
你可以测试一下,把
call slowOutput.bat
替换成call bears.bat
**重要提示:**使用者只需将所有可用内容读入
line
变量。如果生产者足够快,这可能导致获取两个 * 行 *(带CR)。
以bears.bat为例:
Content of line =
Counter: 4<CR>Counter: 3<CR>
如果您的真实的curl命令产生了这个问题,您需要在<CR>
字符处拆分line
。