热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

脚本文件里的HybridScript(混合式脚本)

因为日常需要,经常写一些脚本命令,比如WindowsCMDPowerShellbash之类的。最近学

因为日常需要,经常写一些脚本命令,比如 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(混合式脚本)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 我们 的支持!


推荐阅读
  • 抽空写了一个ICON图标的转换程序
    抽空写了一个ICON图标的转换程序,支持png\jpe\bmp格式到ico的转换。具体的程序就在下面,如果看的人多,过两天再把思路写一下。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文详细介绍了使用C#实现Word模版打印的方案。包括添加COM引用、新建Word操作类、开启Word进程、加载模版文件等步骤。通过该方案可以实现C#对Word文档的打印功能。 ... [详细]
  • Node.js详细安装及环境配置
    1、下载安装根据自己电脑系统及位数选择,我这里选择windows64位.msi格式安装包(官网:https:odejs.orgzh-cndownload).msi和.zip格式区别 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • C# WPF自定义按钮的方法
    本文介绍了在C# WPF中实现自定义按钮的方法,包括使用图片作为按钮背景、自定义鼠标进入效果、自定义按压效果和自定义禁用效果。通过创建CustomButton.cs类和ButtonStyles.xaml资源文件,设计按钮的Style并添加所需的依赖属性,可以实现自定义按钮的效果。示例代码在ButtonStyles.xaml中给出。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 导出功能protectedvoidbtnExport(objectsender,EventArgse){用来打开下载窗口stringfileName中 ... [详细]
  • HTML5网页模板怎么加百度统计?
    本文介绍了如何在HTML5网页模板中加入百度统计,并对模板文件、css样式表、js插件库等内容进行了说明。同时还解答了关于HTML5网页模板的使用方法、表单提交、域名和空间的问题,并介绍了如何使用Visual Studio 2010创建HTML5模板。此外,还提到了使用Jquery编写美好的HTML5前端框架模板的方法,以及制作企业HTML5网站模板和支持HTML5的CMS。 ... [详细]
  • 先下载nodejs针对windows安装安装就行。自定义安装在对应的文件夹就行安装完之后需要在电脑的环境变量里面添加两个路径通过cmd可以查看自己node的版本号最后通过运行npm ... [详细]
author-avatar
鉴湖侠ph
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有