为什么一个`rem`会影响将其输出管道化的代码块?

huangapple go评论105阅读模式
英文:

Why does a rem impact a code block that has its output piped?

问题

我喜欢使用括号括起来的命令块,因为它允许我一次将块中所有命令的输出传输到more(或任何其他命令)。

通常情况下,我也可以在这些块中添加注释(rem)。

然而,我似乎无法同时结合这两个功能:带注释的命令块传输到more(或任何其他命令)根本不执行。为什么会这样?可以解决吗?

@echo off
rem 这个有效(打印X1)
(
    echo X1
)

rem 这个有效(打印X2)
(
    echo X2
) | more

rem 这个有效(打印X3)
(
    rem
    echo X3
)

rem 为什么这个什么都不打印?
(
    rem
    echo X4
) | more

rem 或这个呢?
(
    echo X4
    rem
) | more

rem 这个有效(打印X5)
(
    :: 使用冒号而不是rem
    echo X5
) | more
英文:

I love using blocks of commands enclosed in parentheses, as it allows me to pipe the output of all commands in the block to more (or any other command) at once.

Usually, I can add remarks (rem) inside these blocks, too.

However, I cannot seem to combine the two features: a block with remarks piped to more (or any other command) is not executed at all. Why is that? Can it be solved?

@echo off
rem This works (prints X1)
(
    echo X1
)

rem This works (prints X2)
(
    echo X2
) | more

rem This works (prints X3)
(
    rem
    echo X3
)

rem Why does this print nothing?
(
    rem
    echo X4
) | more

rem Or this?
(
    echo X4
    rem
) | more

rem This works (prints X5)
(
    :: Using colons instead of rem
    echo X5
) | more

答案1

得分: 6

因为折叠的原因。
使用管道会导致两个单独的子cmd.exe进程。
但代码在传递到cmd.exe之前必须被折叠,特别是代码块。

折叠规则很简单,每一行都会被翻译成一个和符号。
所以一个折叠的块看起来像

( echo X1 & echo X2 )

但是用REM你会得到

( REM & echo X4 ) 

REM备注了剩下的行,和符号不再起作用,右括号也被备注了。

如果REM在ECHO之后,问题是一样的

( echo X4 & REM ) 

最后一部分被备注了,所以只剩下( echo X4,右括号丢失了。

但为什么::注释起作用?
看起来::应该会导致和REM一样的错误,但它可以工作!
这是因为::标签在代码块中完全被删除,所以对于一个块的结果行如下:

( 
  :: 我的注释
  echo X4
)

结果很简单:

C:\Windows\system32\cmd.exe  /S /D /c" ( echo X4 )"

如何使REM在管道块中工作?

简单的方法是使用REM.,但它不是真正的REM,不能注释掉和符号或其他特殊字符。

( 
  REM. 这是一个注释,特殊字符在这里不允许
  echo This works
) | more

或者在REM行中使用额外的换行符

(set \n=^
%=此行是必需的=%
)
( 
  REM 这是一个包含 & 和 | 的注释 %%\n%% BREAK
  echo This works
) | more

如何调试折叠的块?

使用cmdcmdline伪变量非常简单

(
  echo Debug %%cmdcmdline%%%
  echo one
  echo two
) | findstr /n "^"

结果:

1:Debug C:\Windows\system32\cmd.exe /S /D /c" ( echo Debug
%cmdcmdline% & echo one & echo two )"
2:one
3:two

另请参阅为什么在代码块内部使用延迟扩展失败?

英文:

It's because of the folding.
Using pipes results in two separate child cmd.exe processes.
But the code has to be folded before it's transferred to a cmd.exe, especially code blocks.

The folding rule is simple, each new line will be translated into an ampersand.
So a folded block looks like

( echo X1 & echo X2 )

But with a REM you get

( REM & echo X4 ) 

The REM remarks the rest of the line, the ampersand has no effect anymore and the closing parenthesis is also remarked.

If the REM is after that ECHO, it's the same problem

( echo X4 & REM ) 

The last part is remarked, so there is only ( echo X4 and the closing parenthesis is missing.

But why :: comments work?
It looks like :: should result in the same error like REM, but it works!
It's because :: labels are completely stripped from a code block, so the resulting line for a block like

( 
  :: My comment
  echo X4
)

Results in simply:

C:\Windows\system32\cmd.exe  /S /D /c" ( echo X4 )"

How to make REM work in piped blocks?

The simple way is to use REM., but it's no quite a real REM, it can't comment out ampersand or other special characters.

( 
  REM. This is a comment, special characters aren't allowed here
  echo This works
) | more

Or use an extra line feed in the REM line

(set \n=^
%=THIS LINE IS REQUIRED=%
)
( 
  REM This is a comment with & and | %%\n%% BREAK
  echo This works
) | more

How to debug folded blocks?

It's simple with the cmdcmdline pseudo variable

(
  echo Debug %%cmdcmdline%%%
  echo one
  echo two
) | findstr /n "^"

Result:

> 1:Debug C:\Windows\system32\cmd.exe /S /D /c" ( echo Debug
> %cmdcmdline% & echo one & echo two )"
> 2:one
> 3:two

See also Why does delayed expansion fail when inside a piped block of code?

huangapple
  • 本文由 发表于 2023年2月8日 13:22:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75381647.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定