如何用python代码编写bash脚本
为了从AndroidManifest.xml获取应用程序的版本,我要执行以下bash命令: /用户/{PATH-TO-SDK}/28.0.3/aapt转储 标记com.squareup.cash.apk | sed-n “s/.versionName='([^'])./\1/p” 我试图在使用操作系统时将其嵌入python脚本中:如何用python代码编写bash脚本,python,bash,Python,Bash,为了从AndroidManifest.xml获取应用程序的版本,我要执行以下bash命令: /用户/{PATH-TO-SDK}/28.0.3/aapt转储 标记com.squareup.cash.apk | sed-n “s/.versionName='([^'])./\1/p” 我试图在使用操作系统时将其嵌入python脚本中: import os bashcommand = " /Users/{PATH-TO-SDK}/28.0.3/aapt dump badging com.squar
import os
bashcommand = " /Users/{PATH-TO-SDK}/28.0.3/aapt dump badging
com.squareup.cash.apk | sed -n "s/.*versionName='\([^']*\).*/\1/p" "
os.system(bashcommand)
但我有一个错误:
SyntaxError:扫描字符串文字时下线
我如何解决这个问题?您的字符串有两个双引号,以部分结束。用三个引号将其括起来:
bashcommand = '''/Users/{PATH-TO-SDK}/28.0.3/aapt dump badging com.squareup.cash.apk | sed -n "s/.*versionName='\([^']*\).*/\1/p"'''
另外,我建议不要使用os.system
,而是使用子流程
:
import subprocess
process = subprocess.Popen(bashcommand.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
编辑
对于那些不想使用Popen
,可以使用call
:
res = subprocess.call(bashcommand, shell=True)
请注意,使用
shell=True
参数可能会带来安全风险(因为打开程序会受到shell注入攻击),因此只能使用经过消毒的输入。如果您有多行语句,请用'
三个引号括起来
阅读
不能嵌套引号;但实际上,我建议您在子流程中运行尽可能少的代码,并使用Python而不是
sed
进行清理
在最近的Python上,您应该优先使用subprocess.run()
,而不是subprocess.Popen()
,并且一定要避免os.system()
,因为它根本不允许您捕获它的输出
subprocess
允许您使用shell=True
传入shell命令(当然,您必须使用正确的引用),但是如果您可以替换sed
调用,就没有理由需要shell,这使整个过程更易于理解和管理,并显著降低了开销。自己将命令行拆分成一个数组是一个很小的代价。(如果你真的不介意的话,也可以使用shlex.split()
如果可以避免的话,不要使用Popen;这个命令显然应该全部在一行上。@tripleee它在我的控制台上给了我没有问题的输出。不确定你到底成功运行了什么。上面将尝试运行两个命令,后者是com.squareup.cash.apk
。您的系统上是否安装了具有此名称的命令?它是做什么的?更多细节,请参见完美!谢谢@triplee,你能解释一下这个错误吗:回溯(最近一次调用最后一次):文件“manifestinfos.py”,第64行,在universal_newlines=True)文件“/Users/***/anaconda3/lib/python3.7/subprocess.py”,第468行,在run output=stdout,stderr=stderr)subprocess.CalledProcessError:Command'['/Users/***/Library/Android/sdk/build tools/28.0.3/aapt','dump','bading','com.squareup.cash.apk']'返回非零退出状态1。该命令未成功完成。如果您知道可以安全地忽略这一点,请取出check=True
;但您确实需要检查该命令的文档,以了解其失败的原因。Hi@triplee,我将您的代码改编为针对多个应用程序循环,但我不理解错误。def getVersionName(pkg_name):result=run(['../aapt',dump',bading',pkg_name],stdout=PIPE,stderr=PIPE,universal_newlines=True)version=result.stdout.split(“VersionName=”)[1]。split(“””[0]当我执行函数getVersionName(“com.ubercab.apk”)时,它只对第一个应用程序有效#getVersionName(“com.bambuna.podcastainct”)我有一个索引器(列表索引超出范围)用于其他应用程序,你知道为什么吗?TY完全简单的解决方法是在sed
脚本周围使用单引号,而不是双引号。也许可以切换到r“原始字符串”
用于命令行,以避免Python使用反斜杠做…事情。
import os
bashcommand = ''' /Users/{PATH-TO-SDK}/28.0.3/aapt dump badging
com.squareup.cash.apk | sed -n "s/.*versionName='\([^']*\).*/\1/p'''
os.system(bashcommand)
from subprocess import run, PIPE
result = run([
'/Users/{PATH-TO-SDK}/28.0.3/aapt',
'dump', 'badging', 'com.squareup.cash.apk'],
stdout=PIPE, stderr=PIPE, check=True,
universal_newlines=True)
version = result.stdout.split("versionName='")[1].split("'")[0]