控制字符和字符串操作

3
使用Jeb在ss64上发布的技巧将退格控制字符保存到变量中时,如果“重叠”退格,则会得到奇怪的结果。

这个例子是在这里发起的一个代码高尔夫挑战:Backhanded^H^H^H^H^H^Hspaces(希望能获得缩短代码的任何提示)。

展开后可能如下所示:

@echo off
setLocal enableDelayedExpansion

for /F %%a in ('"prompt $H&echo on&for %%b in (1) do rem"') do set DEL=%%a

set s=%1
echo %s:^H=!DEL!%

基本上,它使用Jeb的技巧将退格键保存为变量,然后使用字符串操作将输入字符串中所有^H的实例替换为该变量。这对于以下示例和类似的输入正确工作:

C:\>bsp.bat "testing^H^H^H test"
"test test"

然而,当出现“重叠”使用^H时,我得到了以下令人困惑(对我来说)的输出:
C:\>bsp.bat "AAA^HB^H^H"
"A"B

我的问题是 - 以上的例子中,为什么我收到了这个输出而不是预期的 "A"

我必须问一下,你为什么想这样做?你正在使用一个十年未更新的语言来处理未记录的遗留控制台行为,并在这里询问你发现的一些古怪行为。答案几乎肯定已经失传了。 - Ryan Bemrose
1
@RyanBemrose 我为什么想这样做 - 我是一个hacky解决方案的忠实粉丝,尤其是在Batch中进行代码高尔夫比赛。 "失落于历史" - 我们会看到的,我真的很怀疑我的问题的答案是否如此晦涩。我只是不太了解CMD对控制字符或字符串操作的处理。 - unclemeat
3个回答

5

我不明白为什么“期望输出”应该是“A”。请看这个逐字逐句的输出:

bsp.bat "AAA^HB^H^H"
"
"A
"AA
"AAA
"AAA    <- backspace, the cursor is over last "A"
"AAB
"AAB    <- backspace, the cursor is over last "B"
"AAB    <- backspace, the cursor is over second "A"
"A"B

BS字符只是将光标向后移动一个字符。BackSpace键的“标准行为”(也称为“BackSpace echo”)是“BackSpace + space + BackSpace”。

顺便说一下,以下是我获取BS字符的方法:

for /F %%a in ('echo prompt $H ^| cmd') do set BS=%%a

感谢您的解释。我的错误。就像我说的,这只是一个不理解控制字符本身或BackSpace回显概念的问题。我已将字符串操作更改为%s:^H=!D! !D!% - unclemeat

4
""A"B" 的结果是可以预料的,因为退格字符(0x08)<BS> 只会将光标向后移动而不会删除字符。

当你使用PROMPT $H时,它实际上会打印<BS><space><BS>。第一个<BS>向后移动一个位置,空格覆盖(视觉清除)了字符,然后第二个<BS>再次向后移动到您想要的位置。

FOR /F的默认分隔符是<tab><space>,因此您的赋值只保留了第一个<BS>。将分隔符更改为"r",即可获得所需的结果:

"
@echo off
setLocal enableDelayedExpansion

for /F "delims=r" %%a in ('"prompt $H&echo on&for %%b in (1) do rem"') do set DEL=%%a

set s=%1
echo %s:^H=!DEL!%

或者,保留单个<bs>的定义,然后明确地自己覆盖该字符:
@echo off
setLocal enableDelayedExpansion

for /F %%a in ('"prompt $H&echo on&for %%b in (1) do rem"') do set DEL=%%a

set s=%1
echo %s:^H=!DEL! !DEL!%

好答案。为了在代码高尔夫挑战中节省一些字节,我选择了相同的捕获退格字符的方法,并将字符串操作改为%s:^H=!D! !D!%。谢谢。 - unclemeat
1
当你的评论出现时,我正在进行相同的基本编辑。 :-) - dbenham

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接