首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Nushell中的直到循环

Nushell中的直到循环
EN

Stack Overflow用户
提问于 2022-04-29 20:27:04
回答 1查看 272关注 0票数 2

您是如何在Nushell脚本中执行while/until循环的?

由于Nushell有一个相当棒的表/JSON解析系统,所以我一直试图通过它来处理堆栈交换API

首先的挑战之一是循环处理来自API调用的多个可能的页面结果。我的背景(通常是程序性的,有时是面向对象的)让我在Nushell找到了一个构造,比如:

代码语言:javascript
运行
复制
let page = 1
let re = (http (echo "/2.3/questions?fromdate=1648771200&todate=1648944000&order=desc&sort=activity&site=askubuntu&page=" $page) | from json)
let questions = $re.items

while ($re.has_more) {
    let page = page + 1
    let re = (http (echo "/2.3/questions?fromdate=1648771200&todate=1648944000&order=desc&sort=activity&site=askubuntu&page=" $page) | from json)
    let questions = $questions | append $re.items
}

..。或等效的until结构。

我怎么才能在努希尔完成这件事?

注:在上面的示例中使用https://httpie.io/,因为它自动处理Stack所需的gzip压缩(与wget或Nushell的内部fetch命令不同)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-29 20:27:04

简短答覆:

努希尔0.72开始,while循环和可变变量一起被支持,以帮助处理这些循环。until-style循环不受支持,但可以通过whileloop复制(尽管不那么简洁)。

详细信息:

问题中的示例现在可以用以下方法处理:

代码语言:javascript
运行
复制
let baseUri = "https://api.stackexchange.com/2.3/questions?fromdate=1648771200&todate=1648944000&order=asc&sort=creation&site=askubuntu&pagesize=100"
mut page = 1
let pageUri = ((echo $baseUri "&page=" $page) | str collect)
mut result = (http $pageUri | from json )
mut questions = $result.items
while ($result.has_more) {
    $page += 1
    print $page
    let pageUri = ((echo $baseUri "&page=" $page) | str collect)
    $result = (http $pageUri | from json )
    $questions = ($questions | append  $result.items)
}
$questions | where view_count > 100 && view_count < 110 | select view_count title link

结果:

代码语言:javascript
运行
复制
╭───┬────────────┬──────────────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ # │ view_count │                                          title                                           │                                                 link                                                 │
├───┼────────────┼──────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 0 │        103 │ Find reason for &quot;apache2.service: Failed with result &#39;exit-code&#39;.&quot; and │ https://askubuntu.com/questions/1400332/find-reason-for-apache2-service-failed-with-result-exit-code │
│   │            │ &quot;Failed to start The Apache HTTP Server.&quot;                                      │ -and-failed-t                                                                                        │
│ 1 │        103 │ Public folder is forbidden in nginx                                                      │ https://askubuntu.com/questions/1400333/public-folder-is-forbidden-in-nginx                          │
│ 2 │        101 │ WSL Nano scrolling up to see terminal                                                    │ https://askubuntu.com/questions/1400431/wsl-nano-scrolling-up-to-see-terminal                        │
╰───┴────────────┴──────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────╯

是的,Nushell实际上很漂亮-打印结果表。

当然,由于这更像是一个until-style循环,所以它并不像可能的那样简洁,因为它必须在while循环之前和内部重复逻辑。

还可以在0.72 (break)中使用新的早期循环终止特性,以获得更简洁的until-style:

代码语言:javascript
运行
复制
let baseUri = "https://api.stackexchange.com/2.3/questions?fromdate=1648771200&todate=1648944000&order=asc&sort=creation&site=askubuntu&pagesize=100"
mut page = 1
mut questions = []
loop {
    let pageUri = ((echo $baseUri "&page=" $page) | str collect)
    let result = (http $pageUri | from json )
    $questions = ($questions | append  $result.items)
    if $result.has_more {
        $page += 1
    } else {
      break
    }
}

然而,我最初的0.72答案,使用递归函数,仍然是一种有效的处理方法(有时可能更简洁),但请记住,Nushell没有尾递归。

使用递归,Nushell中的基本"while“循环看起来可能如下所示:

代码语言:javascript
运行
复制
def wloop [] {
    let re = (random bool)
    if ($re) { 
        print $re
        wloop
    }
}
$ wloop
$ wloop
$ wloop
true
$ wloop
true
true
true

相应的“直到循环”看起来可能是:

代码语言:javascript
运行
复制
def uloop [] {
    let re = (random bool)
    print $re
    if ($re) { uloop }
}
$ uloop
false
$ uloop
false
$ uloop
true
false

如果您需要修改一个变量,请记住它的作用域是它的块,所以您需要将它传递回递归函数。例如,要使用Stack Exchange API并更新每个调用的页码:

代码语言:javascript
运行
复制
$ let baseUri = "https://api.stackexchange.com/2.3/questions?fromdate=1648771200&todate=1648944000&order=asc&sort=creation&site=askubuntu&pagesize=100"
$ def getAskUbuntuQuestionPageLoop [ page? ] {
    let page = if ( $page == null ) {1} else {$page}
    let pageUri = ((echo $baseUri "&page=" $page) | str collect)
    let re = (http $pageUri | from json )
    
    if ($re.has_more) {
        $re.items | append (getAskUbuntuQuestionPageLoop ($page + 1))
    } else {
        $re.items
    }
}
$ let questions = (getAskUbuntuQuestionPageLoop)

请注意,未来的每个调用都是append编辑的当前结果。

还请注意,返回的结果必须是函数中执行的最后一条语句。

备注:个人意见--我设想Nushell最终会添加一个yield关键字来允许生成器表达式。这将通过允许在reduce中进一步积累结果,从而进一步实现上述示例。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72063354

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档