脚本文件里的 Hybrid Script(混合式脚本)

栏目: 编程工具 · 发布时间: 6年前

内容简介:因为日常需要,经常写一些脚本命令,比如 Windows CMD / PowerShell / bash 之类的。最近学习了一种新的脚本类型:Hybrid script,即混合式脚本,是在一个脚本文件内,同时使用多个语言的语法和对应功能。比如以下这段代码:这是一个用户体验相对比较好的方法。虽然这脚本只是自用,但我自己也是比较烦命令行的。至于任务是下载视频,或者处理音频,亦或删除目录什么的,只是中段执行不同,和本文主旨无关。这脚本的核心难点,便是『如果没有拖拽列表文件,则打开窗口让用户选』这个需求点。CMD

因为日常需要,经常写一些脚本命令,比如 Windows CMD / PowerShell / bash 之类的。最近学习了一种新的脚本类型:Hybrid script,即混合式脚本,是在一个脚本文件内,同时使用多个语言的语法和对应功能。比如以下这段代码:

<# : hybrid.bat
@ECHO OFF
if "%~1" == "" goto SELECT
bin\youtube-dl -a "%~1"
goto :EOF
 
:SELECT
setlocal
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
    bin\youtube-dl -a "%%~I"
)
goto :EOF
:: end Batch portion / begin PowerShell hybrid chimera #>
 
Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }

这段代码的功能是调用 youtube-dl.exe,按预先准备的待下载视频列表指示,下载所有视频。有趣的是,如果你通过拖拽的方式,把列表放到脚本文件图标上,则脚本直接开始按列表下载。

脚本文件里的 Hybrid Script(混合式脚本)

如果没有拖拽,而是双击打开脚本文件,则会跳出一个选择文件的 Windows 对话框,让用户选择一个或者多个列表,然后再开始下载。

脚本文件里的 Hybrid Script(混合式脚本)

这是一个用户体验相对比较好的方法。虽然这脚本只是自用,但我自己也是比较烦命令行的。至于任务是下载视频,或者处理音频,亦或删除目录什么的,只是中段执行不同,和本文主旨无关。

这脚本的核心难点,便是『如果没有拖拽列表文件,则打开窗口让用户选』这个需求点。CMD 是没有 Windows 图形界面下的对话框功能的,但 PowerShell 有。因此便有了这个 Hybrid Script 脚本。

脚本前半段是 Batch 代码,输入下载列表文件路径,执行下载。这个『下载列表文件路径』,或者是用户拖拽获得,或者是用户在选择窗口中操作获得。后半段则是 .ps1 代码,用来绘制选择窗口并把列表路径返回 CMD。

但问题在于,两种代码并不兼容。CMD 并不能识别 PowerShell 代码,而 PS 也无法识别 Batch 代码。如果普通的执行对方的代码,一定会报错的。

于是我们看到,上面这段代码里似乎有几行奇怪的代码:

<# : hybrid.bat
......
goto :EOF
......
:: end Batch portion / begin PowerShell hybrid chimera #>

没错,就是这几行特殊代码,以及另一个非常重要的变量 % ~ f0 ,决定了 Hybrid Script 的可行性。

事实上, < # ..... #> 是 PowerShell 的注释代码,PS1 执行器遇到它时,会直接忽略两者中间的所有内容,执行后面的代码。而 < # :hybrid.bat 对 CMD 而言是个没有指定目标的左向重定向命令。因此 CMD 确实执行了第一行,但没有任何效果。

对于 PS 的结束注释符号 #> ,在 CMD 看来确实有意义。但我们提前用 goto : EOF 直接跳到脚本最末(End-Of-File)的办法,把这一行以及后面的所有代码都跳过了。于是这些代码在 CMD 下的对错就无关紧要了。

以上都明确以后,中间那句 'powershell -noprofile "iex (${%~f0} | out-string)"' 的作用也就容易理解了——Batch 脚本调用了 PowerShell 的执行器,并把这个 hybrid.bat 自己(在 Batch 代码中, % ~ f0 这个变量就是指脚本文件自己)传递给了 PowerShell。

PowerShell 接到消息以后,又执行了一遍这个 Hybrid.bat。这次是 PS 视角,因此上来就忽略了前面整大段的“注释”,直接从 Add - Type - AssemblyName System . Windows . Forms 这段开始,绘制窗口,等待用户选择,获得列表文件路径,然后再返回给 CMD。CMD 最后再执行

for / f "delims=" % % I in ( . . . . . . ) do ( . . . . . . ) 的部分,并根据

goto : EOF

的指示,跳过剩余代码,避免了在 CMD 环境下的报错。

因此,为了正确执行功能,Hybrid Script 的核心思想是:

1. 利用两种语言的注释符号的不同,隐藏非执行环境下的代码。

2. 灵活应用两种语言的特性,确保任一语言下的注释符号本身,对于另一种语言没有负面效果。

3. 首先执行的语言 A,需要把脚本文件自身的路径,传递给另一种语言 B 的执行器。

4. B 语言的执行器,忽略掉被 B 语言注释符号包裹起来的 A 语言代码,执行 B 的代码,如果需要的话,把执行结果返回给 A。

5. A 继续执行剩下的部分,忽略掉被 A 语言的注释符号包裹起来的 B 语言代码。

6. Hybrid Script 至少会执行两遍,可能更多。

———————————————

充分理解 Hybrid Script 思想以后,我们就知道这并不仅仅限于 Batch 和 PowerShell 脚本的混合了。常用的几种脚本语言都可以实现混合代码。实践中:

1. Windows Batch & Windows PowerShell

2. Windows Batch & Linux Bash

3. Windows Batch & Python

4. Windows Batch & Javascript

5. Linux Bash & Python

6. Linux Bash & Javascript

7. NodeJS & Python

8. …

等等组合都可以写出相应的混合代码脚本。

Hybrid Script 能同时利用两种甚至多种语言的方便特性。并且对于各语言组合,相互注释的『套路』是固定的,几部分代码实际功能如何变化并不影响套路。但其实整体来说适用性不广,一来机器上需要同时有两种语言的运行环境,二来 Python JS C# 等几种主流语言都有完备的功能集和函数库,不需要跨语言写作。三来,即使真的需要两种语言,大部分情况下也可以写成两个脚本互相调 用执行。

只有很少的几种情况下需要考虑 Hybrid Script,包括:

1. 因为传播渠道问题,不适合拆分成多个脚本的。比如互联网上常见的『复制粘贴代码到记事本改后缀为 .bat 然后双击运行』。

2. 代码票友,对 A 语言和 B 语言都不甚精通,或者从 A 转 B 的学习过程中,B 还不甚了解,需要用 A 语言的代码补足。

3. A 语言确实功能有限,但胜在编码方便历史普及率高。而产品虽需要却也只需要 B 的极小功能。比如本文示例。

4. 写着玩。


以上所述就是小编给大家介绍的《脚本文件里的 Hybrid Script(混合式脚本)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Math Adventures with Python

Math Adventures with Python

Peter Farrell / No Starch Press / 2018-11-13 / GBP 24.99

Learn math by getting creative with code! Use the Python programming language to transform learning high school-level math topics like algebra, geometry, trigonometry, and calculus! In Math Adventu......一起来看看 《Math Adventures with Python》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具