【问题标题】:Python - How do I shell-scape a variable?Python - 我如何对变量进行 shell-scape?
【发布时间】:2020-04-16 13:59:48
【问题描述】:

我需要从 python 运行以下 shell 脚本:

AliasScript = "osascript -e 'tell application \"Finder\" to make alias at \
POSIX file \"" + dirAlbumName + "\" as alias to \
POSIX file \"" + dirName + "\" as alias'"

os.system(AliasScript + "&> /dev/null")

仅当dirAlbumName 和/或dirName 变量不包含任何元字符(或者它们是否称为特殊字符?)时才有效,例如\'"。例如,如果 dirName = /\/\/\ !@#$%^&*()|?"'"" /\?\/ 会出现语法错误。

如何对这些变量进行外壳转义?我尝试根据从here 阅读的内容使用 shlex,但我无法让它工作。例如,我尝试了shlex.quote(dirName),但它不起作用。

编辑:

需要明确的是,这段代码将在循环中运行数百次,dirNamedirAlbumName 的值不同,所以我不能手动转义它们。

【问题讨论】:

    标签: python macos terminal pycharm


    【解决方案1】:

    您可以使用 python 字符串格式来准确传递您想要的内容,例如您需要执行以下操作:

    dirAlbumName=r"jim&bo"
    dirName=r"jon smith"
    AliasScriptTemplate = r"osascript -e 'tell application \"{0}\" to make alias at \
    POSIX file \"{1}\" as alias to \
    POSIX file \"{2}\" as alias'"
    AliasScript = AliasScriptTemplate.format("Finder",dirAlbumName,dirName)
    AliasScript += r'&> /dev/null'
    os.system(AliasScript)
    

    这里的关键是r 前缀字符串意味着python不会对字符串“做”任何事情,但保持原样。更多细节在这里https://www.linode.com/docs/development/python/string-manipulation-python-3/

    请注意,python 的 subprocess 模块非常适合运行脚本,并且可以让您更好地控制正在执行的操作,包括将 stderr 和 stdout 重定向到文件/变量/,请参阅此处的说明 https://www.programcreek.com/python/example/94463/subprocess.run

    【讨论】:

    • 我刚试过,我得到了:Traceback (most recent call last): File "/Users/pschorn/PycharmProjects/SpotifyIndex/SpotlightIndex.py", line 178, in <module> show_tracks(tracks) File "/Users/pschorn/PycharmProjects/SpotifyIndex/SpotlightIndex.py", line 122, in show_tracks AliasScript.append(r'&> /dev/null') AttributeError: 'str' object has no attribute 'append'
    • 我也刚刚在我的问题中添加了一些内容。
    • 代码的倒数第二行是否缺少括号?
    • 倒数第二行末尾多了一个,已修复。谢谢
    • 我仍然无法让它工作。现在,如果dirAlbumName 包含特殊字符,则不会发生任何事情
    【解决方案2】:

    考虑使用shlex.quote 模块来转义您的dirAlnumNamedirName。我不熟悉您使用的脚本语言,但这就是这里发生的情况。

    >>> import shlex
    >>> dirname="""/\/\/\ !@#$%^&*()|?"'"" /\?\/"""
    >>> print(shlex.quote(dirname))
    '/\/\/\ !@#$%^&*()|?"'"'"'"" /\?\/'
    >>> print (dirname)
    /\/\/\ !@#$%^&*()|?"'"" /\?\/
    >>>
    

    这是一个活生生的例子

    >>> fname = "\name"
    >>> import os
    >>> os.system("touch " +fname)
    touch: missing file operand
    Try 'touch --help' for more information.
    sh: 2: ame: not found
    32512
    >>> import shlex
    >>> os.system("touch " +shlex.quote(fname))
    0
    

    更安全的方法是使用 subprocess 模块并完全避免使用 shell。例如

    >>> import subprocess
    >>> subprocess.Popen(['touch', '\name'])
    >>> _.wait()
    0
    

    【讨论】:

    • 你能告诉我如何在我的问题中为上面的代码使用子流程模块吗?我真的很感激。
    • 恐怕我不知道您编写脚本时所用的语言。
    • 这是苹果脚本。但是,我已经放弃了这个问题。我会确保变量中没有任何特殊字符。
    • 问题在于 os.system 依赖于 shell 将命令解析为单词(例如,ls -l 转换为 ls-l)。这会带来引用等问题。如果您自己将命令拆分为单词,则不涉及shell并且不会发生引用问题。
    【解决方案3】:

    我已经复制了您的问题。我创建了一个名为“$#$%@@”的文件夹。每当出现“#”时,您都需要传递一个转义字符。 例如:

    /path/to/folder/$\#$%@@
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-10
      • 1970-01-01
      • 1970-01-01
      • 2018-01-22
      • 1970-01-01
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多