首页 > 解决方案 > 我可以在 powershell 读取主机中使用现有变量吗

问题描述

我正在使用“read-host -prompt”在powershell中编写一个简单的脚本,以便我可以输入一些文本,然后用于创建一些环境变量。

有没有办法在脚本的后续运行时,读取主机消息将显示变量的现有值(如果存在)?如果不是我想要的,那么接受我的新输入来更改该变量?

例如 ...

$myvar = read-host -prompt "whats your value" 我输入 10 将 $myvar 值设置为 10

下次运行脚本时,“whats your value”将显示 10,如果我在不更改值的情况下按 Enter 键,它将再次使用值 10 .. 如果我输入新值,它会将 $myvar 更新为新值

谢谢你的帮助

标签: powershell

解决方案


如果我理解正确,您正在寻找PowerShell 7.1中实现的两个功能:Read-Host

  • (a)使用默认值预先填充编辑缓冲区,用户可以按原样接受或修改。

    • 另一种方法是通过字符串通知用户,-Prompt如果他们不输入新值,将使用什么值,但是这样您将无法区分用户选择默认值还是只是想要中止提示(但是他们可以用 来做Ctrl-C)。
  • (b)保持用户输入值的持久历史记录,该历史记录(至少)记住(至少)最近输入的值,跨 PowerShell 会话

注意:Read-Host目前是准系统。为 PowerShell 本身提供丰富的交互式命令行编辑体验的模块是PSReadLine,如果它的功能(包括持久历史记录和修改编辑缓冲区)可用于用户代码以进行通用提示,那就太好了 - 请参阅GitHub 提案 #881通过
表面处理这种增强可能是最好的选择,或者至少可以在那里实现预填充编辑缓冲区的能力:参见GitHub 提案 #14013Read-Host

请参阅下面的 (a) 和 (b) 的有限自定义实现。


(a) 目前只能通过一种解决方法,并且只能在 Windows 上,在常规控制台窗口Windows 终端中(它在过时的PowerShell ISE中不起作用(足够可靠)谢谢,CFou,以及 Visual Studio Code 的集成终端只有在启动调试会话后立即单击将焦点放在它上面时它才有效):

# The (default) value to pre-fill the Read-Host buffer with.
$myVar = 'This is a default value.'

# Workaround: Send the edit-buffer contents as *keystrokes*
# !! This is not 100% reliable as characters may get dropped, so we send
# !! multiple no-op keys first (ESC), which usually works.
(New-Object -ComObject WScript.Shell).SendKeys(
  '{ESC}' * 10 + ($myVar -replace '[+%^(){}]', '{$&}')
)

$myVar = Read-Host 'Enter a value'  # Should display prompt with value of $myVar

注意:该-replace操作对于转义默认值中的字符是必要的,否则这些字符会对.SendKeys().

(b) 要求您实现自己的持久性机制,显而易见的选择是使用文件

这是一种仅存储最近输入的值的简单方法。

  • 每个提示支持多个历史值也将支持调用in Read-Host,例如使用向上箭头和向下箭头循环浏览历史记录,从 PowerShell 7.1 开始支持。
# Choose a location for the history file.
$historyFile = "$HOME/.rhhistory"

# Read the history file (which uses JSON), if it exists yet.
$history = Get-Content -Raw -ErrorAction Ignore $historyFile | ConvertFrom-Json
$defaultValue = 'This is a default value.'

# Get the 'myVar' entry, if it exists, otherwise create it and use the default value.
$myVar = 
  if (-not $history) { # no file yet; create the object to serialize to JSON later
    $history = [pscustomobject] @{ myVar = '' }
    $defaultValue
  } elseif (-not $history.myVar) { # file exists, but has no 'myVar' entry; add it.
    $history | Add-Member -Force myVar ''
    $defaultValue
  } else {  # return the most recently entered value.
    $history.myVar
  }

# Prompt the user.
(New-Object -ComObject WScript.Shell).SendKeys(
  '{ESC}' * 10 + ($myVar -replace '[+%^(){}]', '{$&}')
)
$myVar = Read-Host 'Enter a value'

# Validate the value...

# Update the history file with the value just entered.
$history.myVar = $myVar
$history | ConvertTo-Json > $historyFile

推荐阅读