我需要创建一个集成脚本来设置一些环境变量,使用wget下载文件并运行它。
挑战在于它需要是可以在Windows PowerShell和bash / shell上运行的SAME脚本。
这是shell脚本:
#!/bin/bash
# download a script
wget http://www.example.org/my.script -O my.script
# set a couple of environment variables
export script_source=http://www.example.org
export some_value=floob
# now execute the downloaded script
bash ./my.script
这与PowerShell中的相同:
wget http://www.example.org/my.script -O my.script.ps1
$env:script_source="http://www.example.org"
$env:some_value="floob"
PowerShell -File ./my.script.ps1
所以我想知道这两个脚本是否可以合并并在任一平台上成功运行?
我一直试图找到一种方法将它们放在同一个脚本中,让bash和PowerShell.exe忽略错误,但没有成功。
任何猜测?
答案 0 :(得分:7)
有可能;我不知道这是多么兼容,但PowerShell将字符串视为文本并最终显示在屏幕上,Bash将它们视为命令并尝试运行它们,并且都支持相同的函数定义语法。因此,将一个函数名称放在引号中,只有Bash会运行它,放入"退出"在引号中,只有Bash会退出。然后编写PowerShell代码。
NB。这是有效的,因为两个shell中的语法重叠,并且您的脚本很简单 - 运行命令并处理变量。如果您尝试使用更高级的脚本(if / then,for,switch,case等),那么另一种语言可能会抱怨。
将其保存为dual.ps1
,以便PowerShell对此感到满意,chmod +x dual.ps1
以便Bash运行它
#!/bin/bash
function DoBashThings {
wget http://www.example.org/my.script -O my.script
# set a couple of environment variables
export script_source=http://www.example.org
export some_value=floob
# now execute the downloaded script
bash ./my.script
}
"DoBashThings" # This runs the bash script, in PS it's just a string
"exit" # This quits the bash version, in PS it's just a string
# PowerShell code here
# --------------------
Invoke-WebRequest "http://www.example.org/my.script.ps1" -OutFile my.script.ps1
$env:script_source="http://www.example.org"
$env:some_value="floob"
PowerShell -File ./my.script.ps1
然后
./dual.ps1
在任一系统上。
编辑:您可以通过使用不同的前缀对代码块进行注释来包含更复杂的代码,然后让每种语言过滤掉自己的代码并eval
(通常的安全警告适用于eval),例如:采用这种方法(纳入Harry Johnston的建议):
#!/bin/bash
#posh $num = 200
#posh if (150 -lt $num) {
#posh write-host "PowerShell here"
#posh }
#bash thing="xyz"
#bash if [ "$thing" = "xyz" ]
#bash then
#bash echo "Bash here"
#bash fi
function RunBashStuff {
eval "$(grep '^#bash' $0 | sed -e 's/^#bash //')"
}
"RunBashStuff"
"exit"
((Get-Content $MyInvocation.MyCommand.Source) -match '^#posh' -replace '^#posh ') -join "`n" | Invoke-Expression
答案 1 :(得分:1)
#!/usr/bin/env sh
true --% ; : '
<#'
#
# sh part
#
echo "hello from bash/dash/zsh"
echo "do whatver you want just dont use #> directly"
echo "e.g. do #""> or something similar"
# end bash part
exit #>
#
# powershell part
#
echo "hello from powershell"
echo "you literally don't have to escape anything here"
语法高亮告诉我们几乎整个故事
柠檬绿部分(; : '
)只是参数
浅蓝色很特别
<#
是评论的开始
对于 bash 来说完全不同。
--%
并不特殊,它只是一个参数(true
忽略参数)
但是 ;
是特殊的,这就是命令的结尾
那么:
实际上就是“什么都不做”的shell命令
然后 '
开始一个在下一行结束的字符串参数
很好,感谢
--%
)让我们不用在 powershell 中开始一个字符串,而在 bash 中开始一个字符串<#
和 #>
几乎没有。 Powershell 合法地没有缺点。 Bash 警告很容易修复,而且非常罕见
"#>"
更改为 "#"">"
' blah #> '
更改为 ' blah #''> '
。#>
并且由于某种原因您不能更改该评论(这就是我所说的非常罕见的意思),您实际上可以使用 #>
,您只需要添加 re - 在您的 true --%
评论之后添加前两行(例如 #>
等)#
删除字符串的一部分(我敢打赌,大多数人甚至不知道这是一个 bash 功能)。下面的示例代码
https://man7.org/linux/man-pages/man1/bash.1.html#EXPANSIONvar1=">blah"
echo ${var1#>}
# ^ removes the > from var1
要解决这个问题,还有其他方法可以从字符串的开头删除字符,请改用它们。