检查环境变量中是否包含文本变量的子字符串。

huangapple go评论59阅读模式
英文:

Check for text variable substring in environment variable

问题

Here is the translated content you requested:

尝试创建一个批处理文件,通过调用 sqlcmd.exe 运行 SQL 脚本,我正在尝试让批处理文件在执行之前自动检测 exe 文件的存在并将其添加到 %PATH% 中。我可以保证它会出现在主机上的某个地方,但不确定在哪里。

查看 Stack Overflow 上的许多 示例,这表明检测字符串 A 是否在字符串 B 中的最稳健方法是使用 echo 命令并使用管道 findstr 命令来考虑大小写不敏感等因素。

考虑到这一点,我在我的批处理文件中有以下内容:

@echo off

REM 确保我们可以找到 SQL 解释器
echo 正在检查 SqlCmd.exe,请稍候...
setlocal EnableDelayedExpansion
for /f "delims=" %%F in ('dir "%programfiles%\sqlcmd.exe" /s/b') do (
    set filepath=%%~dpF
    echo "Found SQL interpreter in: !filepath!"

    REM 它是否已经在 PATH 中?
    echo %path% | findstr /c:"!filepath!" 1>nul
    if errorlevel 1 (
        echo "SqlCmd 不在当前环境变量 PATH 中,正在设置..."
        set path=%path%;!filepath!
    )
)

并且输出如下:

正在检查 SqlCmd.exe,请稍候...
\Microsoft 在此时间点上是意外的。

尽管输出中没有出现 Found SQL interpreter in: 文本,但实际问题似乎出现在下一行可执行代码上(通过删除它并运行进行测试):

echo %path% | findstr /c:"!filepath!" 1>nul

它似乎正在echo整行并执行,而不是将 %path% 输出并进行 findstr 管道处理。我尝试添加引号但没有效果。

我几乎完成了,但似乎还需要一步编码或调整才能使其正常工作。

更新 1
我测试机器上的 PATH 变量内容如下:

C:\Program Files\Common Files\Oracle\Java\javapath;C:\Program Files\Microsoft MPI\Bin\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files (x86)\Microsoft SQL Server0\Tools\Binn\;C:\Program Files\Microsoft SQL Server0\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server0\DTS\Binn\;C:\Program Files\Microsoft SQL Server0\DTS\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC0\Tools\Binn\;C:\Program Files\Microsoft SQL Server0\Tools\Binn\;C:\Program Files\dotnet\;C:\ProgramData\chocolatey\bin;C:\Program Files (x86)\Windows Kits\Windows Performance Toolkit\;C:\Program Files\Git\cmd;C:\Users\User\.dotnet\tools;C:\Program Files\Java\jdk-17.0.3.1\bin;C:\Users\User\AppData\Local\Programs\Microsoft VS Code\bin;C:\Program Files\Azure Data Studio\bin
英文:

While trying to create a batch file that runs a SQL script by calling out to sqlcmd.exe, I'm trying to get the batch file to detect for the presence of the exe and add it to %PATH% automatically before executing. I can guarantee that it will be somewhere on the host but not where.

Looking at the many examples on SO, this suggests that the most robust way of detecting if string A is in string B is to echo out and pipe to findstr to account for case insensitivity, etc.

With this in mind, I have the following in my batch file;

@echo off

REM Ensure we can find the sql interpreter
echo Checking for SqlCmd.exe, please wait...
setlocal EnableDelayedExpansion
for /f "delims=" %%F in ('dir "%programfiles%\sqlcmd.exe" /s/b') do (
    set filepath=%%~dpF
    echo "Found SQL interpreter in: !filepath!"

    REM is it part of the PATH already?
    echo %path% | findstr /c:"!filepath!" 1>nul
    if errorlevel 1 (
        echo "SqlCmd is not part of the current ENVAR PATH, setting..."
        set path=%path%;!filepath!
    )
)

And has the following output;

Checking for SqlCmd.exe, please wait...
\Microsoft was unexpected at this time.

Despite the text Found SQL interpreter in: not appearing in the output, the actual issue seems to be in the next executable line (tested by removing it and running):

echo %path% | findstr /c:"!filepath!" 1>nul

It seems to be echoing out the whole line and executing rather than echoing out the %path% and piping to findstr. I've tried adding quotes to no effect.

I'm almost there but missing an encoding step/tweak to get this to work.

Update 1
The PATH variable contents on my test machine is;

C:\Program Files\Common Files\Oracle\Java\javapath;C:\Program Files\Microsoft MPI\Bin\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files (x86)\Microsoft SQL Server0\Tools\Binn\;C:\Program Files\Microsoft SQL Server0\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server0\DTS\Binn\;C:\Program Files\Microsoft SQL Server0\DTS\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC0\Tools\Binn\;C:\Program Files\Microsoft SQL Server0\Tools\Binn\;C:\Program Files\dotnet\;C:\ProgramData\chocolatey\bin;C:\Program Files (x86)\Windows Kits\Windows Performance Toolkit\;C:\Program Files\Git\cmd;C:\Users\User\.dotnet\tools;C:\Program Files\Java\jdk-17.0.3.1\bin;C:\Users\User\AppData\Local\Programs\Microsoft VS Code\bin;C:\Program Files\Azure Data Studio\bin

答案1

得分: 0

以下是翻译好的部分:

经过MagooMofi的非常有帮助的建议以及一些实验,我调整了逻辑,使其

  • 正确考虑了大小写(我漏掉了/I
  • 修复了语法问题,从/s/b改为/s /b
  • 添加了新的setlocal EnableExtensions标志
  • 将循环变量更改为J

我也尝试了其他建议,但它们对批处理文件的运行没有实际影响(除了一些微妙的差异)。然后我遇到了一个障碍;

set path="%path;%%~dpF"

这导致%PATH%有一个前导和尾随的",这破坏了对%PATH%引用的所有内容。省略"意味着SET导致原始错误。

相反,我放弃了尝试设置%PATH%,直接使用了对SqlCmd.exe的引用。最终的批处理文件如下;

@echo off

REM 确保我们能找到sql解释器
echo 正在检查是否存在SqlCmd.exe,请稍候...
setlocal EnableExtensions
setlocal EnableDelayedExpansion
for /f "delims=" %%J in ('dir "%programfiles%\sqlcmd.exe" /s /b') do (
    echo%%~dpJ 找到SqlCmd
    set sqlcmd="%%J"
    goto 退出
)

:退出
%sqlcmd% /?

对于仍然希望设置%PATH%变量并阅读有关变量扩展等的人,Mofi的链接如下以方便参考;

英文:

After very helpful suggestions from Magoo and Mofi and some experimentation, I tweaked the logic such that it was

  • Correctly accounting for case (I had ommitted the /I)
  • Fixed the sytax issue of /s/b to /s /b
  • Added the new setlocal EnableExtensions flag
  • Changing the loop variable to J

I had also applied the other suggestions but they had no defacto effect (valid subtlties and distinctions aside) on the running of the batch file. I then hit the hurdle of;

set path="%path;%%~dpF"

This resulted in %PATH% having a leading and trailing " which broke all references to anything %PATH% was referencing. Leaving out the " meant that the SET resulted in the original error.

Instead I ditched my attempt to set %PATH% entirely and just used the found reference to SqlCmd.exe directly. The final batch file is like so;

@echo off

REM Ensure we can find the sql interpreter
echo Checking for SqlCmd.exe, please wait...
setlocal EnableExtensions
setlocal EnableDelayedExpansion
for /f "delims=" %%J in ('dir "%programfiles%\sqlcmd.exe" /s /b') do (
    echo SqlCmd found at %%~dpJ
    set sqlcmd="%%J"
    goto exit
)

:exit
%sqlcmd% /?

For those looking to still set the %PATH% variable, and read up on variable expansion, etc, Mofi's links are listed below for convenience;

huangapple
  • 本文由 发表于 2023年4月20日 00:33:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76056883.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定