通过函数保持全局变量值管道

通过函数保持全局变量值管道

我写了一个小 bash 脚本,sed在一些 html 页面上使用它来提取一些 url。

为了避免每次抓取变量中的 sed 结果然后再次读取它,我简单地创建了 3 个函数并通过管道连接在一起。

first_function $1 | second_function | third_function

这么说吧:

  • 第一个函数从给定的列表中查找项目 url链接地址( $1)
  • 第二个函数从每个管道 URL 中提取图像src
  • 第三个函数组装输出 HTML

现在我回显$lot_urlsecond_function所以我可以read将它third_function一起$img_url放入 HTML 中。

会更干净如果我可以将它作为一个可以访问的全局变量 second_functionthird_function似乎我不能。

随着函数之间传递的值数量的增加,这一点变得更加必要。

这里是完整的示例代码:

first_function(){
    curl -s "$1" | sed -nr '
        #extract sub urls
    '
}

second_function(){
    while read lot_url; do
        echo "$lot_url"
        curl -s "$lot_url" | sed -nr '
            #extract img src
        '
    done
}

third_function(){
    while read lot_url; read img_url; do
        echo "<a href="$lot_url"><img src="$img_url" /></a>"
    done
}

first_function "$1" | second_function | third_function

答案1

管道的两侧处于不同的过程中。您不能在这些进程之间共享变量。如果您想共享数据,您要么必须通过管道传递数据,要么使用备用通信通道。如果您需要备用通信渠道,则您超出了 shell 的功能,请切换到真正的编程语言。

在这里,在第二个管道中并行lot_urlimg_url我来说似乎是一个很好的解决方案。我会在同一条线上传递它们。假设您的 URL 已正确转义,则不需要任何特定的引用,您可以在同一行上传递它们。这样做的优点是允许img_url每个 中的 s数量可变lot_url

second_function(){
    while read lot_url; do
        echo "$lot_url"
        curl -s "$lot_url" | sed -nr -e '
            #extract img src
        ' -e "s>^>$lot_url >"
    done
}

third_function(){
    while read lot_url img_url; do
        echo "<a href="$lot_url"><img src="$img_url" /></a>"
    done
}

答案2

我认为一个 while 循环在这里就可以了。我认为这实际上没有什么区别,因为无论如何你每次迭代都会调用可执行文件。这样你共享您所希望的全局变量。喜欢:

source_cmd |
    while read var
    do  fn1 "$var" |
        fn2 "$var"
    done

但我认为最好还是稍微改变一下工作流程 - 该函数只不过是一组基于数组的 shell 命令。现在您没有将数组用于其中任何一个,因此它确实应该用于指出一组命令的共同目的 - 我能看到的最常见的似乎是curl ... | sed ....所以我建议你应该让它成为一个可以接受参数的函数。所以结果可能是这样的:

curl_sed() { url=$1 && shift
    curl -s "$url" | sed -nr "$*"
}
fn() { URL=$1 && shift
    set -- '#extract sub url sed script' \
           '#extract img src sed script'
    curl_sed "$URL" "$1" | 
        while read lot_url
        do  IFS='
';          printf '<a href="'"$lot_url"'"><img src="%s" /></a>\n' \
            $(curl_sed "$lot_url" "$2")
        done
}

你已经接受了吉尔斯对这个问题的回答——显然是几年前,我没有意识到——但是这是另一个这展示了与我的方法类似的方法,并且我认为它更适合此目的。

相关内容