将一列中的项目重复到另一列中的对应编号 不预先拆分的替代解决方案

问题描述

我有一个文件

A 3
B 5
C 1
D 2

我想将第1列中的项目输出为第2列中相应值的次数,就像

A
A
B
B
B
B
B
C
D
D

我已将文件分为chr和pos两个列表

chr=(A B C D)
pos=(3 5 1 2)

二手

for i in ${chr[@]}; do for j in $(seq ${pos[@]}); do echo "${i}"; done; done

但是我得到了结果,chr中的每个项目都重复了pos中的第一个项目

A
A
A
B
B
B
C
C
C
D
D
D

如果我也不要分割文件,那会更好

解决方法

您的脚本中的问题是j in $(seq ${pos[@]})。在这里,pos[@]在第二列中列出了 all 个数字。若要解决此问题,只需要使用当前行中的数字。目前,这是不可能的,因为您需要当前行号ln才能访问pos[ln]。您可以将第一个循环更改为for ln in "${!chr[@]}",并用i替换所有${chr[ln]}。但是,有更好的解决方案。

不预先拆分的替代解决方案

while read -r value repeat; do
    yes "$value" | head -n "$repeat";
done < inputFile

或(如果值不包含特殊符号)

xargs -n2 sh -c 'yes "$0" | head -n "$1"' < inputFile
,

您可以使用for循环:

#!/bin/bash

filename="something.txt"

while read -r char count
do
    for ((i=0; $i<$count; i++))
    do
        echo $char
    done
done < "$filename"
,

可以使用简单的awk完成

awk 'NF == 2{for (i=1; i<=$2; i++) print $1}' file
A
A
A
B
B
B
B
B
C
D
D
,

我可能会从chr[]数组中提取索引,然后将索引用于所需的结果。

首先,我们看一下数组的样子:

$ typeset -p chr
declare -a chr=([0]="A" [1]="B" [2]="C" [3]="D")
$ typeset -p pos
declare -a pos=([0]="3" [1]="5" [2]="1" [3]="2")

您可以从其他答案中看出,有几种方法可以生成所需的输出。对于使用两个数组的解决方案,我将修改原始代码,例如:

for i in ${!chr[@]}                        # loop through the chr[] array indices
do
    for (( j=0; j<"${pos[${i}]}"; j++ ))   # replace seq with a for loop/counter
    do
        echo "${chr[${i}]}"                # display our chr[] array value
    done
done

A
A
A
B
B
B
B
B
C
D
D