You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过commandArgs将twoBitToFa输出从Bash传递给R?

问题:Shell向R传递twoBitToFa输出内容失败

当前Bash脚本中,$P(BED文件路径)、$G(基因组版本)、$O(输出格式)三个参数已正常定义。当$O为fasta时,通过UCSC的twoBitToFa工具能成功生成.fa文件,代码如下:

if [ "$O" = "fasta" ]
    then
        awk '{print $0" "$1":"$2"-"$3}' "$P" | 
        twoBitToFa -bed=stdin -udcDir=. "$twobit" stdout > "${P%.bed}".fa
    fi

注:此处stdout与>确实冗余,直接移除stdout即可,twoBitToFa默认输出到标准输出,重定向依然生效。

当$O为bed时,需要将$P、$G、$O以及twoBitToFa的输出内容传递给R脚本GetSeq_R.r,跳过生成.fa文件的步骤,但两次尝试均失败:

失败尝试1:将输出存入变量传递

尝试把twoBitToFa的输出存入myvar再传给R,但R脚本仅能收到$P、$G、$O三个参数,无法获取myvar内容:

if [ "$O" = "bed" ]
    then
        awk '{print $0" "$1":"$2"-"$3}' "$P" | 
        myvar=$(twoBitToFa -bed=stdin -udcDir=. "$twobit" stdout) \
        Rscript \
        GetSeq_R.r \
        $P \
        $G \
        $O \
        $myvar
    fi

R脚本开头代码:

args = commandArgs(trailingOnly=TRUE); print(args)

输出结果:

[1] "TAD-1_template.bed" "hg38"               "bed"  

失败尝试2:使用tee传递

使用tee后,twoBitToFa的输出能在控制台显示,但依然无法传递给R:

if [ "$O" = "bed" ]
    then
        awk '{print $0" "$1":"$2"-"$3}' "$P" | 
        twoBitToFa -bed=stdin -udcDir=. "$twobit" stdout | tee \
        Rscript \
        GetSeq_R.r \
        $P \
        $G \
        $O
    fi

解决方案

方法1:通过标准输入(stdin)传递序列数据

twoBitToFa的输出是多行FASTA格式内容,不适合作为命令行参数传递(会被空格/换行分割为多个参数,且存在长度限制)。正确做法是将序列数据通过标准输入传给R脚本,同时把$P、$G、$O作为命令行参数传递:

修改Bash脚本中的bed分支代码:

if [ "$O" = "bed" ]
    then
        awk '{print $0" "$1":"$2"-"$3}' "$P" | 
        twoBitToFa -bed=stdin -udcDir=. "$twobit" stdout |
        Rscript GetSeq_R.r "$P" "$G" "$O"
    fi

修改R脚本GetSeq_R.r,读取标准输入内容:

args = commandArgs(trailingOnly=TRUE)
# 获取命令行参数
bed_path <- args[1]
genome <- args[2]
output_format <- args[3]

# 读取标准输入的FASTA内容
fasta_content <- readLines(file("stdin"))
print("Received FASTA content:")
print(fasta_content)

方法2:使用临时文件传递(适合超大序列数据)

若twoBitToFa输出内容极大,标准输入效率可能不足,可使用临时文件中转:

if [ "$O" = "bed" ]
    then
        # 创建临时文件
        temp_fasta=$(mktemp)
        awk '{print $0" "$1":"$2"-"$3}' "$P" | 
        twoBitToFa -bed=stdin -udcDir=. "$twobit" stdout > "$temp_fasta"
        # 传递临时文件路径给R
        Rscript GetSeq_R.r "$P" "$G" "$O" "$temp_fasta"
        # 删除临时文件
        rm "$temp_fasta"
    fi

对应R脚本修改:

args = commandArgs(trailingOnly=TRUE)
bed_path <- args[1]
genome <- args[2]
output_format <- args[3]
temp_fasta_path <- args[4]

fasta_content <- readLines(temp_fasta_path)
print(fasta_content)

完整修改后的Bash脚本

for arg in "$@"; do
  shift
  case "$arg" in
      "--path")         set -- "$@" "-P" ;; 
      "--genome")       set -- "$@" "-G" ;; 
      "--output")       set -- "$@" "-O" ;; 
      "--help")         set -- "$@" "-h" ;; 
       *)               set -- "$@" "$arg"
  esac
done

while getopts ":P:G:O:h" OPT
do
    case $OPT in
  P) P=$OPTARG;;
  G) G=$OPTARG;;
  O) O=$OPTARG;;
  h) help ;; 
  \?)
      echo "Invalid option: -$OPTARG" >&2
      usage
      exit 1
      ;; 
  :)
      echo "Option -$OPTARG requires an argument." >&2
      usage
      exit 1
      ;; 
    esac
done


num_col=$(awk "{print NF; exit}" "$P")  # 优化:无需cat,直接awk读取文件

if [ "$num_col" = 3 ]
then
echo -e "\n\n3 column bed file detected; no directional considerations for sequences \n\n"
    if [ "$G" = "hg38" ]
    then
        twobit="https://hgdownload.cse.ucsc.edu/goldenpath/hg38/bigZips/hg38.2bit"
    fi    
    if [ "$G" = "hg19" ]
    then
        twobit="https://hgdownload.cse.ucsc.edu/goldenpath/hg19/bigZips/hg19.2bit"
    fi
    if [ "$O" = "fasta" ]
    then
        # 去掉冗余的stdout
        awk '{print $0" "$1":"$2"-"$3}' "$P" | 
        twoBitToFa -bed=stdin -udcDir=. "$twobit" > "${P%.bed}".fa
    fi
    if [ "$O" = "bed" ]
    then
        awk '{print $0" "$1":"$2"-"$3}' "$P" | 
        twoBitToFa -bed=stdin -udcDir=. "$twobit" stdout |
        Rscript GetSeq_R.r "$P" "$G" "$O"
    fi
fi

内容的提问来源于stack exchange,提问作者Doda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 03:55:16