【问题标题】:Assistance with transpose function using Bash使用 Bash 协助转置功能
【发布时间】:2019-10-24 09:55:46
【问题描述】:

我想转置评分脚本中提供的给定矩阵。我不能使用 AWK。该函数必须用 Bash 编写。我有以下代码,其中 AWK 与提供的分级脚本完美配合。非 AWK 脚本返回错误,即它不是对合的或它不是正确的尺寸。总而言之,所有输出看起来都很相似,我很困惑为什么它们看起来与评分脚本不同。如果有人可以帮助将 AWK stript 转换为不使用 AWK 的 Bash。

转置 1 - 一种读取文件的方法

DONE=false
until $DONE;
do
    read -a myLine || DONE=true
    for ((i=0;i<"${#myLine[@]}";i++))
    do
        temp_array[$i]+=" ${myLine[$i]}"
    done
done < $1

for ((i=0;i<${#temp_array[@]};i++))
do
    printf "%s\t" ${temp_array[i]} >> temp_file
    printf "\n" >> temp_file
done

转置 2 - 读取文件。将所有行读入一个数组。

while read -a myLine || [[ ${#myLine[@]} -gt 0 ]]
do
    for ((i=0;i<"${#myLine[@]}";i++))
    do
        temp_array[$i]+=" ${myLine[$i]}"
    done
done < $1

for ((i=0;i<${#temp_array[@]};i++))
do
    printf "%s\t" ${temp_array[i]} >> temp_file
    printf "\n" >> temp_file
done

cat temp_file
rm temp_file

两者都工作并且似乎具有相同的输出。

此代码与评分脚本完美配合:

cp $1 $temp_input    #copy file to temp file named temp_input
awk '{ for (i=1; i<=NF; i++) {a[NR,i] = $i} }
NF>p { p = NF }
END { 
    for(j=1; j<=p; j++) {
        str=a[1,j]
        for(i=2; i<=NR; i++)
    {str=str"    "a[i,j];}
    printf str"\n"}
}' $temp_input # for loop to transpose temp_input file contents
rm $temp_input

预期结果是一个非对合的转置矩阵。来自非 AWK 代码和使用 AWK 提供的代码的结果应该具有相同的精确输出。请帮忙。

【问题讨论】:

  • “非自愿”是一个不寻常的错误消息。使用的确切措辞是什么?你的意思是“内卷”吗?您提供了两个您说可以工作的 bash 脚本,那么问题是什么?您应该提供一些证明问题的测试数据。见stackoverflow.com/help/minimal-reproducible-example
  • 拼写检查更改了单词。我们稍后会更新。不,bash 脚本不起作用,因此出现错误。工作的就是 AWK 脚本。因此不允许使用 AWK。否则我不会提供任何测试数据。
  • 为了清楚起见,2 bash 脚本将使用制表符分隔符转置矩阵。然而,编写 AWK 也是为了做同样的事情。当我使用 AWK 脚本运行评分脚本时,我得到了满分。当我使用 NON AWK 脚本运行它时,评分脚本返回错误并且没有给出分数。
  • 你说No test data provided otherwise I would have,那么如何测试你的脚本呢?我们不在乎作业说什么,您必须提供一些东西,以便我们在提出解决方案之前测试我们的解决方案。然后你说两个 bash 脚本都不起作用,后来又说它们不起作用。令人困惑!
  • 问题是...... awk 是这种换位的更好语言。作为一种胶水语言,sh (bash) 是一种很好的灵活的语言……但是一旦我们开始实现诸如编程低级任务或结构化文本处理之类的东西……好吧这是“故意”的痛苦。

标签: bash awk transpose


【解决方案1】:

所以将 awk 脚本重写为 bash。我使用read -a 将单行读入数组。然后,您只需计算行数 NR 并计算字段数 NF 并复制 awk 脚本。

由于您没有提供任何数据进行测试,我需要自己创建一些,希望您在下一个问题中包含一些示例输入和示例输出。

我使用关联 bash 数组在 bash 中复制 a[1,0] 索引,就像在 awk 中一样。

cat << EOF > file
1  2  3  4
5  6  7  8
9 10 11 12
EOF

echo -------------- awk
< file awk '{ for (i=1; i<=NF; i++) {a[NR,i] = $i} }
NF>p { p = NF }
END { 
    for(j=1; j<=p; j++) {
        str=a[1,j]
        for(i=2; i<=NR; i++)
    {str=str"    "a[i,j];}
    printf str"\n"}
}'

echo ------------ bash

# same in bash
# note indexes start with 0
declare -A a
NR=0
while IFS=$' \t' read -r -a line; do
  for i in ${!line[@]}; do
    a[$NR,$i]="${line[$i]}"
  done
  ((NR++)) ||:
done < file
NF=$i
for ((j = 0; j <= NF; j++)); do
  str="${a[0,$j]}"
  for ((i = 1; i < NR; i++)); do
    str+="    ${a[$i,$j]}"
  done
  printf "%s\n" "$str"
done

将输出:

-------------- awk
1    5    9
2    6    10
3    7    11
4    8    12
------------ bash
1    5    9
2    6    10
3    7    11
4    8    12

在repl.it 中测试和编写。

【讨论】:

  • 此代码不像您所说的那样工作。输出为:
    3 3 3 7 7 7 11 11 11
  • No. It does work, as provided in repl.it online bash。如果没有,请提供MCVE,例如。在在线服务中对其进行编码并提供链接。如果没有最小的可重现示例来揭示您提到的“不像您所说的那样工作”行为,我只能玩猜谜游戏。
猜你喜欢
  • 2011-02-05
  • 1970-01-01
  • 2023-02-13
  • 1970-01-01
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 2017-03-01
  • 1970-01-01
相关资源
最近更新 更多