在python代码中插入bash脚本

时间:2018-08-17 10:35:30

标签: python bash grep pipe

我正在尝试从python代码执行bash脚本。 bash脚本在for循环内的管道中包含一些grep命令。当我运行bash脚本本身时,它没有给出任何错误,但是当我在python代码中使用它时,它说:grep:write error。

我在python中调用的命令是:

subprocess.call("./change_names.sh",shell=True)

bash脚本是:

#!/usr/bin/env bash

for file in *.bam;do new_file=`samtools view -h $file | grep -P '\tSM:' | head -n 1 | sed 's/.\+SM:\(.\+\)/\1/' | sed 's/\t.\+//'`;rename s/$file/$new_file.bam/ $file;done

我想念什么?

2 个答案:

答案 0 :(得分:1)

在运行不需要命令行中任何内容的外壳程序的简单命令时,请勿使用shell=True

subprocess_call(["./change_names.sh"])

shell脚本中存在多个问题。这是评论式重构。

#!/usr/bin/env bash

for file in *.bam; do
    # Use modern command substitution syntax; fix quoting
    new_file=$(samtools view -h "$file" |
        grep -P '\tSM:' |
        # refactor to a single sed script
        sed -n 's/.\+SM:\([^\t]\+\).*/\1/p;q')
    # Fix quoting some more; don't use rename
    mv "$file" "$new_file.bam"
done

grep -P在这里似乎不是必需的或有用的,但是由于没有输入看起来像的例子,我也很犹豫地将其重构为sed脚本。我希望我已经正确地猜出了您的sed版本使用的\+\t转义符不是完全可移植的。

更好的解决方案可能是将更多内容重构到Python脚本中。

import glob

for file in glob.glob('*.bam'):
    new_name = subprocess.check_output(['samtools', 'view', '-h', file])
    for line in new_name.split('\n'):
        if '\tSM:' in line:
            dest = line.split('\t')[0].split('SM:')[-1] + '.bam'
            os.rename(file, dest)
            break

答案 1 :(得分:0)

您好,请尝试以下修改,以解决您的问题。

for file in *.bam;do new_file=`unbuffer samtools view -h $file | grep -P '\tSM:' | head -n 1 | sed 's/.\+SM:\(.\+\)/\1/' | sed 's/\t.\+//'`;rename s/$file/$new_file.bam/ $file;done

否则尝试将您的标准错误重定向到dev / null,如下所示:

for file in *.bam;do new_file=`samtools view -h $file >2>/dev/null | grep -P '\tSM:' | head -n 1 | sed 's/.\+SM:\(.\+\)/\1/' | sed 's/\t.\+//'`;rename s/$file/$new_file.bam/ $file;done

此命令samtools view -h $file的实际问​​题在于从python运行脚本时,应提供如下完整路径:-

/fullpath/samtools view -h $file