【问题标题】:Parse file and use some of the fields as variables using the header as name in bash [closed]在bash中使用标题作为名称解析文件并使用一些字段作为变量[关闭]
【发布时间】:2015-01-29 10:04:16
【问题描述】:

我有一个文件,其中第一行包含一系列字段,制表符分隔 (\t)。我正在尝试遍历这些行并将某些字段用作程序的变量。我到目前为止的代码如下:

    {
    A=$(head -1 id_table.txt)
read;
    while IFS='\t' read $A; 
    do
        echo 'downloading '$SRA_Sample_s
        echo $tissue_s
    #out_dir=`echo $tissue_s | sed 's/ /./g'` #Replacing spaces by dots
    #/soft/bio/sequence/sratoolkit-2.3.4-2/bin/fastq-dump.2.3.4 --split-3 --outdir $out_dir --ncbi_error_report $SRA_Sample_s 
    done 
    } <./id_table.txt

输出(错误):

downloading _s Inser

downloading  provided> <no

downloading  provided> <no

downloading  provided> <no

它失败了,因为它没有正确获取字段。也许&lt;&gt; 字符正在制造混乱?不同文件的列名称排序不同,并且某些文件中缺少某些列。我被困在这里。

文件如下所示:

BioSample_s MBases_l    MBytes_l    Run_s   SRA_Sample_s    Sample_Name_s   age_s   breed_s sex_s   Assay_Type_s    AssemblyName_s  BioProject_s    BioSampleModel_s    Center_Name_s   Consent_s   InsertSize_l    Library_Name_s  Platform_s  SRA_Study_s biomaterial_provider_s  g1k_analysis_group_s    g1k_pop_code_s  source_s    tissue_s
SAMN02777951    4698    3249    SRR1287653  SRS607026   SL01    19  SL01    female  RNA-Seq <not provided>  PRJNA247712 Model organism or animal    SICHUAN UNIVERSITY  public  200 <not provided>  ILLUMINA    SRP041998    Chengdu Research Base of Giant Panda Breeding  <not provided>  <not provided>  <not provided>  blood
SAMN02777952    4451    3063    SRR1287654  SRS607028   XB01    12  XB01    male    RNA-Seq <not provided>  PRJNA247712 Model organism or animal    SICHUAN UNIVERSITY  public  200 <not provided>  ILLUMINA    SRP041998    Chengdu Research Base of Giant Panda Breeding  <not provided>  <not provided>  <not provided>  blood
SAMN02777953    4553    3139    SRR1287655  SRS607025   XB02    6   XB02    female  RNA-Seq <not provided>  PRJNA247712 Model organism or animal    SICHUAN UNIVERSITY  public  200 <not provided>  ILLUMINA    SRP041998    Chengdu Research Base of Giant Panda Breeding  <not provided>  <not provided>  <not provided>  blood

【问题讨论】:

  • IFS='\t' 没有按照您想要的方式工作。这是由t 分隔的。使用IFS=$'\t' 来使用标签。这就是为什么你会收到_s Inser 等。
  • 我明白了!那行得通!谢谢。如果您将其发布为答案,我会接受。
  • bioji:你必须写@username 来通知用户你在说些什么。 (例如:@Etan)

标签: bash sed while-loop separator fastq


【解决方案1】:

IFS='\t' 没有按照您想要的方式工作。这是由t 分隔的。使用IFS=$'\t' 来使用标签。

这就是你得到_s Inser等的原因(注意它从t字母开始并截止)。

话虽如此,我完全同意 EdMorton 的观点,即使用 awk 可能是一个更好的主意,尽管我相信通过仔细引用和断言选项卡不会出现在输入文件中,您可以只使用 shell 安全地执行此操作(但 Ed 不止一次向我展示了我最初想法的错误,所以他很可能在想我没有想到的东西。

【讨论】:

  • 我同意,对于这种特殊情况,他可能会接受精心编写的(即不是他开始使用的!)shell 循环。我实际上认为awk | xargs.. 将是最好的方法,但我不能完全确定用于分隔每行 2 个 args 的 xargs 语法!
  • @EdMorton 我认为您需要断言空格在任何地方都没有意义,才能为此使用xargs,然后您可以使用xargs bash -c '/path/to/cmd "$1" "${*:2}"' - 之类的东西或类似的东西。或者,您可能可以让 awk 使用 ORS='\0' 并使用 xargs -n 2 -x bash -c '/path/to/cmd "$1" "$2"' - 但我必须尝试它,它会在最后错过任何非配对行(但我不确定这是一个问题)它也可能会错误配对任何其他错过字段的行。
【解决方案2】:

您可能会发现 awk 脚本比 shell 循环更健壮且使用起来更简单:

$ cat tst.awk
BEGIN { FS="\t" }
NR==1 { for (i=1; i<=NF; i++) f[$i]=i; next }
{
    print "downloading", $(f["SRA_Sample_s"])
    out_dir = $(f["tissue_s"])
    gsub(/ /,".",out_dir)
    cmd = sprintf( "/soft/bio/sequence/sratoolkit-2.3.4-2/bin/fastq-dump.2.3.4 --split-3 --outdir %s --ncbi_error_report %s", out_dir, $(f["SRA_Sample_s"]) )
    print cmd
    #system(cmd); close(cmd)
}

.

$ awk -f tst.awk file
downloading SRR1287653
/soft/bio/sequence/sratoolkit-2.3.4-2/bin/fastq-dump.2.3.4 --split-3 --outdir blood --ncbi_error_report SRR1287653
downloading SRR1287654
/soft/bio/sequence/sratoolkit-2.3.4-2/bin/fastq-dump.2.3.4 --split-3 --outdir blood --ncbi_error_report SRR1287654
downloading SRR1287655
/soft/bio/sequence/sratoolkit-2.3.4-2/bin/fastq-dump.2.3.4 --split-3 --outdir blood --ncbi_error_report SRR1287655

我想说,如果不是因为您调用外部命令,那么您绝对应该避免 shell 循环,因此不仅仅是文本处理。

或者,考虑使用 awk 进行文本处理,然后通过管道传输到 shell 循环以执行外部命令:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==1 { for (i=1; i<=NF; i++) f[$i]=i; next }
{
    gsub(/ /,".",$(f["tissue_s"]))
    print $(f["tissue_s"]), $(f["SRA_Sample_s"])
}

.

$ awk -f tst.awk file |
while IFS=$'\t' read -r out_dir SRA_Sample_s
do
    printf 'downloading %s\n' "$SRA_Sample_s"
    #/soft/bio/sequence/sratoolkit-2.3.4-2/bin/fastq-dump.2.3.4 --split-3 --outdir $out_dir --ncbi_error_report $SRA_Sample_s 
done
downloading SRR1287653
downloading SRR1287654
downloading SRR1287655

【讨论】:

  • 投反对票有什么特别的原因吗?
  • 不是我。 @EtanReisner 发现的错误使我的代码正常工作。我确实在调用外部命令:)
  • 您的方法的问题在于,它让您暴露于一些不适合文本处理的 shell 行为,如通配符、分词、文件名扩展等,因此您可能会遇到非常意外和不受欢迎的情况结果基于您的输入文件的内容。这就是为什么我建议您将 awk 用于文本处理部分,因为它没有这些问题。如果您的输入文件保证始终只包含字母和数字(即没有 RE 或通配元字符,如 . * ? 等),那么您可能会没事。
【解决方案3】:

尝试(根据您的开发风格)

cat id_table.txt \
 | {
   read Header

   while eval "read ${Header}"
    do
      echo "Donwloading ${SRA_Sample_s}"
      echo "${tissue_s}"
    done
   }

【讨论】:

  • 这里我看到cateval 和大括号(在变量名中)的不必要使用。我同意你获取标题的方式。
  • 它不像你写的那样工作。我修复了它在代码中的 while 和 eval 之间添加 IFS=$'\t' 的问题。我喜欢你检索标题的方式,比我的更好。
  • 它对分隔符(制表符或空格)非常敏感。使用在复制/粘贴过程中放置​​一些制表符和空格的样本副本进行测试时会出现很多问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 2014-04-17
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多