【问题标题】:Bash loop producing unwanted duplicate results [duplicate]Bash循环产生不需要的重复结果[重复]
【发布时间】:2019-02-18 07:13:34
【问题描述】:

我在 bash 中工作。我正在尝试在 .txt 文件的字符串中查找唯一的条形码。每个字符串可以包含 3 个条形码。我想识别并标记每个包含我感兴趣的条形码的独特配置。

这是我的起始 reads.txt 文件,其中包含我要评估的字符串。

ABCD1
EFGH2
ABGH1
EFCD2

例如,ABCD1 中包含的条形码为ABCD1

我想要的结果是只识别sring ABCD1EFGH2 并将它们分别存储为result.1.txtresult.2.txt

下面是我的尝试。

# Add the barcode sequences to a bash array
declare -a BARCODES1=(AB EF)
declare -a BARCODES2=(CD GH)
declare -a BARCODES3=(1 2)

# Initialize counter
count=1

# Search for the barcode sequences in the reads.txt file
rm ROUND*
rm result*

for barcode in "${BARCODES1[@]}";
    do
    grep "$barcode1" reads.txt > ROUND1_MATCHES.txt

        for barcode2 in "${BARCODES2[@]}";
        do
        grep "$barcode2" ROUND1_MATCHES.txt > ROUND2_MATCHES.txt

           for barcode3 in "${BARCODES3[@]}";
            do
            grep "$barcode3" ROUND2_MATCHES.txt > ROUND3_MATCHES.txt

                if [ -s ROUND3_MATCHES.txt ]
                then
                mv ROUND3_MATCHES.txt result.$count.txt
                fi

            count=`expr $count + 1`
            done
        done
    done

奇怪的是,这段代码输出了太多的结果文件。运行 head results* 会得到以下结果。

==> result.1.txt <==
ABCD1

==> result.2.txt <==
EFCD2

==> result.3.txt <==
ABGH1

==> result.4.txt <==
EFGH2

==> result.5.txt <==
ABCD1

==> result.6.txt <==
EFCD2

==> result.7.txt <==
ABGH1

==> result.8.txt <==
EFGH2

想要的结果应该是

==> result.1.txt <==
ABCD1

==> result.2.txt <==
EFCD2

【问题讨论】:

  • 不相关,但为什么专门在 bash 中?
  • 我之所以使用 bash,是因为它在我使用的 linux 集群环境中运行良好,而且我比其他语言更容易编写 bash 脚本(我还是个初学者)。当然可以使python中的某些东西起作用。选择使用 bash 是否有我错过的明显优势(速度等)?
  • ¯_(ツ)_/¯ 不知道,只是为了保持 grepping/etc 而不是使用更通用的语言和更好的字符串支持等,这似乎过于复杂和磁盘繁重。
  • 在嵌套的内部循环中使用grep(启动一个全新的程序,从一开始就读取输入文件等)确实是一种严重的代码异味。不过,这不一定是 bash 的问题,而不是它的应用问题。

标签: bash for-loop duplicates


【解决方案1】:

您只想遍历数组的索引

for index in "${!BARCODES1[@]}"; do
    echo "${BARCODES1[index]}${BARCODES2[index]}${BARCODES3[index]}"
done
ABCD1
EFGH2

使用 3 个 嵌套 循环,count 增加 2 * 2 *2 = 8 次


有点不清楚您要做什么:如果您要生成 (AB,EF) 和 (CD,GH) 和 (1,2) 的叉积,您可以这样做

$ printf "%s\n" {AB,EF}{CD,GH}{1,2}
ABCD1
ABCD2
ABGH1
ABGH2
EFCD1
EFCD2
EFGH1
EFGH2

然后,如果您尝试在 reads.txt 中提取与这些字符串之一匹配的行,那么

$ grep -xFf <( printf "%s\n" {AB,EF}{CD,GH}{1,2} ) reads.txt
ABCD1
EFGH2
ABGH1
EFCD2

【讨论】:

    猜你喜欢
    • 2017-09-11
    • 2016-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    相关资源
    最近更新 更多