虚度光阴的一整天:Windows下如何去掉echo中的双引号

《每天进步一点点:学习使用Graphviz》一文中,我介绍了初学者了解&使用graphviz最简便的方法,那就是直接使用命令行。

image.png
(图源 :pixabay)

比如,最简单的生成最简单的“Hello World”关系图,命令如下:

echo 'digraph { Hello -> World }' | dot -Tsvg > output.svg

但是这条命令在Linux下或许会准确无误地执行,在Windows下,却只生成了一个0字节大小的svg文件,内容嘛,自不必多言,当然是空的。

好吧,我还曾试图打开它,得到如下提示信息:

This XML file does not appear to have any style information associated with it. The document tree is shown below.

从代码上,貌似并没有什么问题呀?哪里出错了呢?上述代码的意义就是将echo语句的输出作为输入传递给dot指令,然后在把输出重定向给output.svg。

其中涉及到输入输出重定向的两个操作分别为|(管道操作符)以及>(输出重定向),想对这个两个深入了解的请参考文末链接。

既然我们不清楚哪里出错,那么就逐步调试呗,我们首先测试管道前边的部分,echo 'digraph { Hello -> World }',期望其输出digraph { Hello -> World }

然而在Windows命令行执行上述指令,却发现什么输出都没有。

仔细研究会发现在语句echo 'digraph { Hello -> World }'>被识别为输出重定向,它把ECHO输出的内容,重定向到一个名为World的文件中,这显然不是我们需要的结果。

测试使用转义字符^来对>进行转义,亦即echo 'digraph { Hello -^> World }',倒是可以输出'digraph { Hello -> World }',但是传递给dot依然失败,果断放弃。

这时我想到,既然单引号中的内容会被转义,那么如果使用双引号呢?亦即echo "digraph { Hello -> World }" | dot -Tsvg > output.svg

结果却得到如下提示:

Error: <stdin>: syntax error in line 1 near '"'

看一下echo语句的输出,为"digraph { Hello -> World }",也就是说dot程序不接受""(双引号)作为输入(可以直接执行dot -Tsvg,并输入上述内容验证)。
image.png

现在,问题进一步简化,就变成了,如何脱掉echo输出中的双引号。

原本以为这并不会是个问题,毕竟Linux下echo支持很多参数,而且输出的内容直接是脱双引号的,结果折腾半天才发现,Windows的echo弱到爆!指望参数啥的来搞定,那是不可能啦。

通过参数转换去双引号

经过我不懈努力,找到几个去掉双引号的方案,多数是使用批处理文件调用时通过去掉参数的双引号来实现的:

%~1 Expands %1 and removes surrounding quotation marks.

比如以下这个例子(来自文末链接):

@echo off
setlocal
set mystring="this is some quoted text"
echo mystring=%mystring%
call :dequote %mystring%
echo ret=%ret%
endlocal
goto :eof

:dequote
setlocal
rem The tilde in the next line is the really important bit.
set thestring=%~1
endlocal&set ret=%thestring%
goto :eof

但是我们把代码中字符串换成我们需要的"digraph { Hello -> World }",输出却不是我们想要的样子:

image.png

其实对于上述代码,我们可以简化成如下形式:

@setlocal
@set thestring=%~1
@echo %thestring%
@endlocal

将其保存为myecho.bat,并以类似如下形式调用:

myecho "digraph { Hello }" | dot

是可以得到正确输出的
image.png

但是依然无法正确处理"digraph { Hello -> World }"

通过搜索替换去双引号

另一种方案是通过搜索替换来去掉双引号。

其本质是基于可以使用%var:x=y%构造将所有x替换为y

示例代码如下(来自文末链接):

set I="Text in quotes"
rem next line replaces" with blanks
set J=%I:"=%
echo original %I%
rem next line replaces the string 'in' with the string 'without'
echo stripped %J:in=without%

代码不做更多解读了,同样处理不了我们的问题。

通过set的提示语

无意中又发现一种方案,这个就太牛了,示例如下:
echo | set /p=";lt;h1;gt;Hello;lt;/h1;gt;"

输出如下:
image.png

这段代码我敢保证99%的人看不懂。

我们通过set /?来查看以下帮助信息(部分内容如下):
1698723676718.png

我们会发现/p的作用是带出一串提示信息,然后手动输入从终端变量值。这时候echo以及|(管道操作)起的作用是模拟终端输入回车。

如果后边继续跟|,那么会因为没有额外输入信息,所以提示信息被作为输入传递给之后的程序。

所以以下语句是可以正常工作的:
echo | set /p="digraph { Hello -> World }"| dot -Tsvg > output.svg

我们会得到如下图形:
1698724046809.png

也可以使用如下语句调试一下:
echo | set /p="digraph { Hello -> World }"| dot

image.png

不得不感慨一下,互联网上真的有能人啊!我去理解都费了如此周转,那么这是什么脑回路才能想出来的办法?

然后又不得不感慨一下自己,得多么无聊地浪费大把的时间研究这个?明明只有初学者测试才能用到命令行直接echo的方式。还有就是既然Windows的echo不好用,写一个简单的echo,大概也用不了多久吧!

又是虚度光阴的一整天!😡

相关链接

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now