/bin/sh: -c: 第 0 行:意外标记 `(' 附近的语法错误

/bin/sh: -c: line 0: syntax error near unexpected token `('

arg2 = f'cat <(grep \'#\' temp2.vcf) <(sort <(grep -v \'#\' temp2.vcf) | sortBed -i - | uniq ) > out.vcf'
print(arg2)
try:
    subprocess.call(arg2,shell=True)
except Exception as error:
    print(f'{error}')

当我运行宁此我得到以下错误:

/bin/sh: -c: line 0: syntax error near unexpected token `('   
/bin/sh: -c: line 0: `cat <(grep '#' temp2.vcf) <(sort <(grep -v '#' temp2.vcf) | sortBed -i - | uniq ) > Out.vcf'

但是当我在命令行中 运行 时它起作用了。

Python 的 call() 函数默认调用带有 sh 的命令。 bash 支持进程替换语法,但 sh.

不支持
$ sh -c "cat <(date)"  
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `cat <(date)'

$ bash -c "cat <(date)"
Mon Mar 14 11:12:48 PDT 2022

如果你真的需要使用 bash-specific 语法,你应该可以指定 shell 可执行文件(但我没有尝试过):

subprocess.call(arg2, shell=True, executable='/bin/bash')

直接错误是您的尝试使用了 Bash-specific syntax。您可以使用 executable="/bin/bash" 关键字参数来解决这个问题;但实际上,您为什么要在这里使用复杂的外部管道? Python 除了 sortBed 本机可以做所有这些事情。

with open("temp2.vcf", "r"
      ) as vcfin, open("out.vcf", "w") as vcfout:
    sub = subprocess.Popen(
        ["sortBed", "-i", "-"],
        text=True,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE)

    for line in vcfin:
        if "#" in line:
            vcfout.write(line)
        else:
            sub.stdin.write(line)

    subout, suberr = sub.communicate()

    if suberr is not None:
        sys.stderr.write(suberr)

    seen = set()
    for line in subout.split("\n"):
        if line not in seen:
            vcfout.write(line + "\n")
        seen.add(line)

Python 重新实现稍微笨拙(并且未经测试,因为我没有 sortBed 或您的输入数据)但这也意味着更明显的是,如果您想更改某些内容修改一下。