我在 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}
,然后将此处文档存储在变量${code}
中?目前,此处文档已成功存储在变量中,但此处文档中的变量尚未解析。
从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 上的引号,并且此处文档中的行不是 扩大。
我不打算覆盖或替换@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('/')+""))
。可能不会产生您想要的效果。