【问题标题】:How to use paste command recursively in a shell script如何在 shell 脚本中递归地使用粘贴命令
【发布时间】:2015-05-24 02:37:04
【问题描述】:

我的脚本中有一个粘贴命令。但它没有给出我想要的输出。我的数据文件是

file.txt
1
3
5
4

我的shell脚本是

f1=file.txt
for j in 1..12
do
awk '{printf ("%.1f\n", $1+'$j');}' $f1 > $j_$f1
paste $j_$f1 > ofile.txt  # ofile.txt is a new empty file
done

这个脚本给出的输出为

ofile.txt
2
4
6
5
3
5
7
6
.
.

我想要的输出为

ofile.txt
2  3  4  5  6 ... 13
4  5  6  7  8 ... 15
6  7  8  9  10 .. 17
5  6  7  8  9 ... 16

我也想为下面的脚本做

bonus_company1=10
bonus_company2=25
bonus_company3=50
declare var=("company1" "company2" "company3")
for k in var{[@]}
do for j in jan..dec
   do if [ $j == "jan" ] || [ $j == "may" ] || [ $j == "sep" ]; then
      awk '{printf ("%.1f\n", $1+ '$bonus_$k');}' $f1 > $k_$j_$f1
      elif [ $j -ne "jan" ] && [ $j -ne "may" ] && [ $j -ne "sep" ]; then
      awk '{printf ("%.1f\n", $1+5);}' $f1 > $k_$j_$f1
      fi
      paste $k_$j_$f1 > $k.txt  # $k.txt is a new empty file
   done
done

所以我将为三个公司获得 3 个不同的文件。例如

company1.txt
11  6  6  6  11 .....
13  8  8  8  11 .....
15  10 10 10 15 .....
14  9  9  9  14 .....

【问题讨论】:

    标签: linux shell awk paste


    【解决方案1】:

    我建议在 awk 中完成所有工作,而不是使用 shell 循环:

    awk '{for (i=1; i<=12; ++i) printf "%d%s", $1+i, (i<12?FS:RS)}' "$f1" > output
    

    此循环针对文件的每一行运行并输出所有列,从而无需使用其他工具,例如 paste。三元运算符用于在每列之间输出一个空格(FS),并在行尾输出一个换行符(RS)。


    对于您问题的第二部分,您仍然可以在 awk 中完成大部分工作。

    declare -A companies
    companies=( [company1]=10 [company2]=25 [company3]=50 )
    for c in "${companies[@]}"; do
        awk -v bonus="${companies[c]}" '{for (i=1; i<=12; ++i) 
            printf "%d%s", $i+(i==1||i==5||i==9?bonus:5), (i<12?FS:RS)}' "$f1" > "$c.txt"
    done
    

    我创建了一个关联数组,其中包含每个公司名称及其奖金。循环遍历数组中的每家公司,将奖金作为变量传递给 awk(请注意,我使用-v 执行此操作,而不是使用字符串连接)。循环从 1 到 12,添加第 1、5 和 9 个月的奖金,否则为 5。公司名称(shell 数组的键)用于输出文件。

    【讨论】:

    • 不太清楚你的意思,你应该编辑你的问题来准确解释你想要做什么。
    • 看起来很棒!!那么当我的 j 是不同的字符而不是数字时是否可以这样做,例如对于 {不同公司名称} 中的 j,我的计算相应地不同,例如if [条件为真];然后 awk '{printf "%s\n", $1}。我已经相应地编辑了问题。
    • 我已经编辑了我的答案,以展示您如何解决问题的第二部分。我假设您使用的是支持关联数组(例如 bash)的 shell,部分原因是您在尝试中使用 == 进行比较。
    • 非常感谢@Tom。它非常好。关于 bash- 是的,我使用 bash shell。请问为什么if命令是==(双等号),awk命令是=(单等号)。我对 linux 和脚本不太了解。
    • @Roselover 在 awk 中,== 用于检查是否相等,= 用于分配。在 shell 中,检查两个字符串是否相等的标准方法是使用 [ "$str1" = "$str2" ],但 bash 也支持使用 ==,使其更像大多数其他语言。
    【解决方案2】:

    我不明白,你为什么要走这么复杂的路。你可以用更简单的方式来做:

    第二个:

    for k in var{[@]}
    do awk '{printf("%.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n", $1+"$bonus_$k", $1+5, $1+5, $1+5, $1+"$bonus_$k", $1+5, $1+5, $1+5, $1+"$bonus_$k", $1+5, $1+5, $1+5);}' file.txt > $k_file.txt
    done
    

    【讨论】:

      猜你喜欢
      • 2020-02-14
      • 2016-10-01
      • 2011-04-25
      • 2019-09-02
      • 1970-01-01
      • 2015-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多