如何遍历列表并在 bash / awk 中作为变量传递

Posted

技术标签:

【中文标题】如何遍历列表并在 bash / awk 中作为变量传递【英文标题】:How to loop through a list and pass as variable in bash / awk 【发布时间】:2018-11-28 21:14:41 【问题描述】:

更新问题:

我有一个config.file,我在其中定义了一些最终在不同脚本中调用的变量。

$cat config.file

#1 Accession number ref
ref=L41223.2

#2 Accession number SRA
SRA=SRA7361534

#3 Path to SRA 
path_SRA='/Volumes/5TB/sra/'

#4 Path to ref
path_ref='/Volumes/5TB/results/species1/'

#3(通往 SRA 的路径)是不变的,永远不会改变。对于其他变量($ref$sra$path_ref),我想从input.file 的不同字段中逐一阅读:

$cat input.file
species1 L41223.2 SRA7361534
species2 D45023.5 SRA9473231
species3 L42823.6 SRA0918881
...

所有这些变量在script.sh 中被多次调用:

#!/bin/bash

# Path to the configuration file
. /Users/Main/config.file

# Use NCBI's e-utilities to download reference files
esearch -db nucleotide -query $ref | efetch -format fasta > $path_ref$ref.fasta

# Using NCBI's sratoolkit to download SRA file
prefetch $SRA
cd $path_SRA
mv *.sra $path_ref

# Decompress the SRA file
cd $path_ref; if fastq-dump --split-3 $SRA.sra ; then

echo "SRA file successfully decompressed. Deleting the SRA file now..."
    rm $SRA.sra 
    else
    echo "Could not decompress SRA file"
    fi

# Use bwa to align DNA reads to the reference sequence
cd $path_ref; 
bwa index -p INDEX $ref.fasta
bwa aln -t $core INDEX *_1.fastq > 1.sai
bwa aln -t $core INDEX *_2.fastq > 2.sai
bwa sampe INDEX 1.sai 2.sai *_1.fastq *_2.fastq | samtools view -hq 5 > $SRA.Q5.sam

# Use samtools for conversion
samtools view -bT $ref.fasta $SRA.Q5.sam > $SRA.Q5.bam
samtools sort $SRA.Q5.bam -o $SRA.sorted

# use bedtools for coverage
bedtools genomecov -d -ibam $SRA.sorted.bam > $SRA.gencov.txt

# use awk for extraction
awk '$2 ~ /81|161|97|145/ print $0' $SRA.Q5.sam > $SRA.OTW.sam
samtools view -bT $ref.fasta $SRA.OTW.sam > $SRA.OTW.bam
samtools sort $SRA.OTW.bam -o $SRA.OTW.sorted.bam

# Extract FLAG, POS, CIGAR and TLEN for outward-oriented reads
awk '$2 ~ /81|161|97|145/ print $2, $4, $6, $9' $SRA.Q5.sam > $SRA.OTW.txt

# Get per-base coverage for outward-oriented reads
bedtools genomecov -d -ibam $SRA.OTW.sorted.bam > $SRA.OTW.gencoverage.txt

# Simplify the output by averaging read coverage over 50 bp window; prints the average count value and last genomic position
awk 'sum+=$3; count++ FNR % 50 == 0 print $2, (sum/count); count=sum = ""' $SRA.OTW.gencoverage.txt > $SRA.OTW.50sum.txt

#### End of the script

我想做的是从input.file“读取”到config.file。第一个字段 (species1...) 将用作 $path_ref 的输入,字段 2 (L41223.2...) 将用作 $ref 的输入,第三个字段 (SRA7361534...) 将用作输入对于 $SRA 变量。完成第一轮(基本上是第一行)后,script.sh 将再次运行并从第 2 行读取字段 1,2 和 3,依此类推。基本上是一个循环,但比下面的答案要复杂一些,因为在脚本的不同位置调用了不同的变量。

这适用于一个变量,但是我无法使用在整个脚本中调用的三个不同变量来实现它:

while read -r c1 c2 c3; do
  bwa index -p INDEX $c2.fasta
  # place rest of your script here
done < input.file

非常感谢。

【问题讨论】:

这会是什么样子?比如:“用 input.file 的第一行更新 config.file,运行 script.sh,然后是 input.file 的下一行,运行 script.sh,等等……”? 是的,比我写的要简单得多。那么你会如何定义 ref 变量呢? 将 script.sh 添加到您的问题中。 我添加了一段脚本;基本上我把它称为另一个需要它作为输入的程序(bwa)的一部分。我只是为 $ref 值添加一个后缀 (.fasta)。 @TobySpeight 感谢您的意见。我试图让这个问题更笼统,以供其他人也可能使用,并且可能在此过程中失去了一些清晰度。我用实际的 config.file 和完整的脚本更新了问题。 【参考方案1】:

script.sh 中,在. /Users/Main/config.file 行之后,添加以下行:

number_of_inputs=$(wc -l < input.file)
for (( i=1 ; i <= number_of_inputs ; i++ )); do
  # extract columns $1, $2, $3 here, from line $i - please change appropriately
  ref=$(     awk "NR==$iprint \$1" input.file)
  SRA=$(     awk "NR==$iprint \$2" input.file)
  path_ref=$(awk "NR==$iprint \$3" input.file)

然后在文件末尾添加一个done,这样整个事情就会遍历input.file每一行中的值,并相应地设置值

【讨论】:

以上是关于如何遍历列表并在 bash / awk 中作为变量传递的主要内容,如果未能解决你的问题,请参考以下文章

如何在bash中的awk内动态比较变量?

如何使用for循环将文本文件中的一行字符串作为Bash中另一个脚本的单独变量传递[重复]

如何检查变量是不是未设置并在我的 bash 前奏中使用 set -u? [复制]

如何遍历图像列表并在 Tkinter 中显示它们

如何遍历地图列表并在颤动列表视图中显示文本小部件?

如何将字符串列分配给变量并在 Bash 脚本的输出中引用它