【问题标题】:In Bash, how can a here-document contain a variable and then be stored in a variable?在 Bash 中,here-document 如何包含变量然后存储在变量中?
【发布时间】:2015-01-31 00:54:18
【问题描述】:

我在 Bash 脚本中有如下内容:

URL="${1}"
IFS= read -d '' code << "EOF"
import urllib2
from BeautifulSoup import BeautifulSoup
page = BeautifulSoup(urllib2.urlopen("${URL}"))
images = page.findAll('img')
for image in images:
    print(image["src"])
EOF
python <(echo "${code}")

如何更改此处文档的定义方式(例如不使用read),以便在此处文档中解析变量${URL},然后将此处文档存储在变量@987654324中@?目前here-document已经成功存储到变量中,但是here-document中的变量并没有被解析。

【问题讨论】:

  • 我强烈建议在sys.argvos.environ 上传递URL,而不是替换到您的脚本中——那样会存在代码注入漏洞。考虑一个包含"+__import__('shutil').rmtree('/')+"URL

标签: bash variables heredoc


【解决方案1】:

EOF中删除引用:

URL="${1}"
IFS= read -d '' code <<EOF
import urllib2
from BeautifulSoup import BeautifulSoup
page = BeautifulSoup(urllib2.urlopen("${URL}"))
images = page.findAll('img')
for image in images:
    print(image["src"])
EOF
python <(echo "${code}")

根据man bash

如果 word 中的任何字符被引用,则分隔符是 word 上的引号删除, 和 here-document 中的行不是 展开。

【讨论】:

  • 按要求回答 bash 问题(因此,我赞成),但会导致应用程序容易受到代码注入漏洞的攻击。
  • 是的,我同意@CharlesDuffy。我不太了解python,无法在脚本中提出修复建议。
  • @anubhava 非常感谢您的帮助。对于任何想要阅读此处文档的 Bash 手册页部分的人,您可以使用以下命令生成手册页的 PDF:man -t bash | ps2pdf - bash.pdf
  • 一个简单的修复方法是在heredoc的开头import os,导出URL中的值,然后调用urllib2.urlopen(os.environ['URL'])
【解决方案2】:

我不打算覆盖或替换对@anubhava 给出的字面问题的(完全正确的)答案——该答案是正确的,并且在被替换为 的文档不是 源码,其用法完全合适。


将变量替换为代码(无论是在heredoc 中还是在其他地方)实际上是一种相当危险的做法——您可能会遇到Bobby Tables 的表亲。

更好的方法是在带外发送变量,以防止任何解析为代码的可能性。在 awk 中,这是通过 -vkey=val 完成的;对于 Python,一种简单的方法是使用环境:

export URL="${1}"
IFS= read -d '' code << "EOF"
import urllib2, os
from BeautifulSoup import BeautifulSoup
page = BeautifulSoup(urllib2.urlopen(os.environ['URL']))
images = page.findAll('img')
for image in images:
    print(image["src"])
EOF
python <(echo "${code}")

对原始代码的更改:

  • 分配URL时使用export
  • Python 中的import os
  • Python 中对os.environ['URL'] 的引用。

至于为什么这种方法更可取——考虑一下如果您正在处理一个给定的包含字符串"+__import__('shutil').rmtree('/')+" 的 URL 会发生什么。跑步

page = BeautifulSoup(urllib2.urlopen(""+__import__('shutil').rmtree('/')+""))

...可能不会达到你想要的效果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    • 2016-09-22
    • 2020-09-30
    • 2016-08-17
    • 1970-01-01
    • 2013-02-07
    • 2016-01-07
    相关资源
    最近更新 更多