[玩转系统] 周五乐趣:PowerShell 天气小工具
作者:精品下载站 日期:2024-12-14 08:01:52 浏览:12 分类:玩电脑
周五乐趣:PowerShell 天气小工具
最近,Twitter 上的某人向我推荐了一种可以在 PowerShell 会话中使用来显示天气信息的资源。这显然是一个成熟且备受推崇的来源。一旦我弄清楚了基础知识,我自然想看看我还能用什么来做到这一点。这就是我的想法。
我今天要讨论的所有内容都涉及使用 Invoke-RestMethod 来使用 REST API。您可以在浏览器中测试的主要 URI 是 http://wttr.in。在 URI 中包含一个位置,例如 http://wttr.in/chicago。但情况会变得更好。 API 源代码和文档可以在 https://github.com/chubin/wttr.in 找到。一旦我花了一点时间研究我能做什么,我就确定了一个像这样的基本命令:
Invoke-RestMethod -Uri http://wttr.in/Syracuse?format=2 -UseBasicParsing -DisableKeepAlive
我觉得这很酷。尽管表情符号仅显示在支持它们的终端控制台中,例如在 Windows 终端中运行的 PowerShell 会话。在 PowerShell ISE 或 VS Code 控制台中运行此程序的运气会较差。
现在我需要推动这个概念。
设置位置格式
构建一个快速脚本来运行此命令非常简单。我什至添加了一个位置参数。该位置可以是邮政编码或地名。我希望创建包含位置的输出。但我想确保该位置的格式正确。
if($Location-match'^([a-zA-Z\s\.\,])+$'){
$Location=[System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ToTitleCase($location.tolower())
}
如果位置是字符串,例如“chicago”,则此文本片段会将其转换为“Chicago”。像“las vegas”这样的字符串会变成“Las Vegas”。
使用当地时间
当我开发代码时,我添加了当前日期和时间。但后来我意识到,如果我在另一个地点(例如拉斯维加斯)运行脚本,并显示东部时区的时间,可能会令人困惑。我需要获取该位置的时区,以便我可以相应地调整时间。
在遇到可选的 v2 API 之前,我在基本 wttr.in 请求中找不到包含该信息的任何内容。格式类似于 http://v2.wttr.in/chicago。不幸的是,没有办法以结构化数据(如 JSON 或 XML)的形式获取结果。所以我不得不求助于正则表达式来解析时区名称。我构建了一个辅助函数来做到这一点。
FunctionGetTZ{
Param([string]$location)
Write-Verbose"Gettingv2datafromwttr.infor$location"
$tmp=Invoke-RestMethod-uri"http://v2.wttr.in/$location"-disableKeepAlive-useBasicParsing
$rx=[System.Text.RegularExpressions.Regex]::new("\b([a-z_]+\/[a-z_]+)\b","IgnoreCase,Multiline")
$timezone=$rx.match($tmp).Value
Write-Verbose"Detectedtimezone$timezone"
$timezone
}
这会给我一个像 America/Chicago 这样的值。下一步是确定时区偏移量。幸运的是,我在 http://worldtimeapi.org 上有另一个使用 REST API 的代码片段。使用此 API,我创建了一个自定义对象。
我的自定义对象包括该时区的当地时间,然后我可以在输出中使用它。
用 ANSI 让它变得漂亮
最后一步是让它变得漂亮。我想使用 ANSI 和特殊字符在天气和位置信息周围绘制彩色线框。通常,这并不太困难,因为我可以计算线长度。
然而,表情符号字符串存在一些挑战。尽管 PowerShell 可能会在两个不同位置显示相同的长度,但如果天气表情符号不同,则可能会导致间距混乱。这意味着我的结束 |因为线路可能会随着天气变化而关闭。我还没有找到一种方法来解决使用表情符号时的字偶距问题,因此我求助于使用 Write-Host。
通过这种方法,我可以保存上一行的光标位置,显示天气行,移动光标,然后显示结束 |。
Write-Host$line1
Write-Host$line2
Write-Host$line3a-NoNewline
#getthecursorposition
$pos=$host.ui.RawUI.CursorPosition
#adjustit
$pos.x=$line1.Length-$boxAnsi.Length-1
#movethecursor
$host.ui.RawUI.CursorPosition=$pos
#writetheclosingboxelement
Write-Host$line3b
Write-Host$line4
我并不为这个黑客感到自豪,但它确实有效。
ANSI 序列被编写为在 Windows PowerShell 或 PowerShell 7 中运行。以下是完整的脚本。
#requires-version5.1
#seehttps://github.com/chubin/wttr.inforAPIinformation
#thismustberuninaWindowsTerminalsessionthatsupportstheglyphs
#oruse-Forceifyouknowyouare.
[cmdletbinding()]
Param([string]$Location="Syracuse,NY",[switch]$Force)
FunctionTestWT{
$parent=Get-CimInstance-ClassNamewin32_process-Filter"processid=$pid"-PropertyParentProcessID
(Get-Process-Id$parent.ParentProcessId).ProcessName-eq"WindowsTerminal"
}
FunctionGetTZ{
Param([string]$location)
Write-Verbose"Gettingv2datafromwttr.infor$location"
$tmp=Invoke-RestMethod-uri"http://v2.wttr.in/$location"-disableKeepAlive-useBasicParsing
$rx=[System.Text.RegularExpressions.Regex]::new("\b([a-z_]+\/[a-z_]+)\b","IgnoreCase,Multiline")
$timezone=$rx.match($tmp).Value
Write-Verbose"Detectedtimezone$timezone"
$timezone
}
FunctionGetTZData{
[cmdletbinding()]
[OutputType("pscustomobject","TimeZoneData")]
Param(
[Parameter(Position=0,Mandatory,ValueFromPipeline,
HelpMessage="EnteratimezonelocationlikePacific/Auckland.Itiscasesensitive.")]
[string]$TimeZoneArea,
[parameter(HelpMessage="Returnraw,unformatteddata.")]
[switch]$Raw
)
Begin{
Write-Verbose"Starting$($myinvocation.mycommand)"
$base="http://worldtimeapi.org/api/timezone"
}#begin
Process{
Write-Verbose"Gettingtimezoneinformationfor$TimeZoneArea"
$target="$base/$TimeZoneArea"
Try{
$data=Invoke-RestMethod-Uri$target-DisableKeepAlive-UseBasicParsing-ErrorActionStop-ErrorVariablee
}
Catch{
Throw$e.innerexception
}
if($data-AND$Raw){
$data
}
elseif($data){
if($data.utc_offset-match"\+"){
$offset=($data.utc_offset.substring(1)-as[timespan])
}
else{
$offset=($data.utc_offset-as[timespan])
}
[datetime]$dt=$data.DateTime
[pscustomobject]@{
PSTypename="TimeZoneData"
Timezone=$data.timezone
Abbreviation=$data.abbreviation
Offset=$offset
DaylightSavingTime=$data.dst
Time=$dt.ToUniversalTime().Addseconds($data.raw_offset)
}
#(Get-Date($data.datetime-split"[\+-]\d{2}:\d{2}")[0])
}
}#process
End{
Write-Verbose"Ending$($myinvocation.mycommand)"
}#end
}#closeGetTZData
#charactersforbuildingalinebox
$charHash=@{
upperLeft=[char]0x250c
upperRight=[char]0x2510
lowerRight=[char]0x2518
lowerLeft=[char]0x2514
horizontal=[char]0x2500
vertical=[char]0x2502
}
Write-Verbose"Gettingweathersummaryfor$location"
#ANSIsequences
$boxAnsi="$([char]0x1b)[38;5;11m"
$closeAnsi="$([char]0x1b)[0m"
$textAnsi="$([char]0x1b)[38;5;191m"
#convertlocationtotitlecaseifitiswords
if($Location-match'^([a-zA-Z\s\.\,])+$'){
$Location=[System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ToTitleCase($location.tolower())
}
if($Force-OR(TestWT)){
$w=Invoke-RestMethod-Uri"http://wttr.in/{$location}?format=2"
Write-Verbose"Gettinglocaltimesettingsfor$Location"
$localtime=gettzdata(gettz$location)
[string]$date="{0:g}"-f$localtime.time
$data=($w.trim())-replace"\s+",""
#internalsumoftheindividualelements.Tryingtofigureoutkerningorspacing
#$internalLength=$($data.split()|foreach{$_.length}|measure-object-sum).sum
$header="{0}"-f$location
$headerAnsi="{0}{1}"-f$textAnsi,$header
$value="{0}{1}"-f$textAnsi,$data
$line1="{0}{1}{2}{3}{4}"-f$boxAnsi,$charHash.upperleft,$date,([string]$charHash.horizontal*($data.length-$date.length)),$charhash.upperRight
$line2="{0}{1}{2}{3}{4}"-f$boxAnsi,$charHash.Vertical,$headerAnsi.padright($line1.length-1),$boxAnsi,$charHash.Vertical
$line3a="{0}{1}{2}"-f$boxAnsi,$charHash.Vertical,$value
#($value.padright($header.length))
$line3b="{0}{1}"-f$boxAnsi,$charHash.Vertical
$line4="{0}{1}{2}{3}{4}"-f$boxAnsi,$charHash.Lowerleft,([string]$charHash.horizontal*($data.length+2)),$charhash.LowerRight,$closeAnsi
Write-Host$line1
Write-Host$line2
Write-Host$line3a-NoNewline
#getthecursorposition
$pos=$host.ui.RawUI.CursorPosition
#adjustit
$pos.x=$line1.Length-$boxAnsi.Length-1
#movethecursor
$host.ui.RawUI.CursorPosition=$pos
#writetheclosingboxelement
Write-Host$line3b
Write-Host$line4
else{
Write-Warning"ThisneedstoberuninaWindowsTerminalsession."
}
}
下一步
我应该把它变成一个带有别名的函数,以使其易于运行。我可能会更深入地研究 wttri.in 的源文件,看看我是否无法直接进行其中一些调用。这可能会更容易同时获取时区信息。我还可以尝试将其添加到我的 PowerShell 提示功能中,并将其显示在我的会话的一角。
尝试一下,玩得开心,然后让我知道您的想法。
更新
我已在 GitHub 上发布了此函数的更新版本:https://gist.github.com/jdhitsolutions/f2fb0184c2dbab107f2416fb775d462b。该版本接受管道输入。
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag