【问题标题】:text manipulation by addition and multiplication通过加法和乘法操作文本
【发布时间】:2021-01-26 20:30:57
【问题描述】:

我有一个名为“test_file”的文本文件,其中包含 6 行和 7 列,如下所示

 0.00 5.8 2.0  5.0 6.0 8.0 0.0
  10.00 5.8 2.0  1.0 1.0 1.2 9.6
  10.00 9.3 2.2  2.0 1.4 2.5 9.6
  30.00 9.3 2.2  1.2 1.5 1.9 1.4
  30.00 9.3 2.2  3.2 2.4 1.2 4.1
  60.00 9.8 3.5  1.4 2.7 3.2 4.5

我想在第二列和第三列中进行一些文本操作。

在第三列中,前两行值应该相同(2.0 和 2.0),接下来的三行值只是第二行值的 0.2 增量(2.0+0.2=2.2,2.0+0.2=2.2,2.0+0.2= 2.2)。但是,我不想更改最后一行,我想保持原样。

在第二列之后,前两行的值应该只是第三列的前两行与 2.9 的乘积。 同样,第二列的下三行只是第三列的下三行与 4.227 的乘积

我根本不想更改的其他列值。

现在我想依次更改第三列的前两行值,2.1,2.2....2.5,然后是相同的增量和乘法。

例如,当我将第三列的前两行值从原来的 2.0 更改为 2.1 时,预期的输出应该是

0.00 6.09 2.1  5.0 6.0 8.0 0.0
  10.00 6.09 2.1  1.0 1.0 1.2 9.6
  10.00 9.722 2.3  2.0 1.4 2.5 9.6
  30.00 9.722 2.3  1.2 1.5 1.9 1.4
  30.00 9.722 2.3  3.2 2.4 1.2 4.1
  60.00 9.8 3.5  1.4 2.7 3.2 4.5

我想以不同的名称保存输出文件,例如 file2.1.txt....file2.5.txt

【问题讨论】:

    标签: shell for-loop awk sh


    【解决方案1】:

    awk 来救援!

    $ awk 'p {print p} 
             {pp=$0; v=$3; $3+=0.1; $2*=$3/v; p=$0} 
         END {print pp}' file | column -t
    
    0.00   6.09     2.1  5.0  6.0  8.0  0.0
    10.00  6.09     2.1  1.0  1.0  1.2  9.6
    10.00  9.72273  2.3  2.0  1.4  2.5  9.6
    30.00  9.72273  2.3  1.2  1.5  1.9  1.4
    30.00  9.72273  2.3  3.2  2.4  1.2  4.1
    60.00  9.8      3.5  1.4  2.7  3.2  4.5
    

    由于你想对最后一条记录进行特殊处理,所以使用上一条记录p延迟处理,同时你想要不修改最后一条记录,所以将原来的上一条记录存储在pp中并在END打印。延迟打印会打印修改后的记录,最后一条不会被修改。

    您也可以指定数字格式,但我认为这并不重要...

    要运行多个增量,只需添加一个外部循环

     $ for inc in {1..5}; 
       do awk -v inc=$inc '...
                           ... $3+=(inc/10) ...
                           ...' file > file."$inc".txt
    
       done
    

    您可以将增量(实际上是增量的 10 倍)作为变量传递给awk 脚本,在脚本和输出文件名中使用。 awk 脚​​本中的唯一变化是增量。

    【讨论】:

    • @lijun,请阅读代码并尝试不同的增量。这应该不难,因为只有一行处理计算。您可以将输出重定向到添加> output.file.name的文件。
    • 你不能像这样嵌套awk 脚本,请参阅我的更新。外循环是多次运行awk 的bash 循环。还有另一种方法可以在 awk 脚本中执行此操作。
    • awk 脚本中唯一的变化是增量。 ... 只是您需要从原始脚本中复制的占位符。抱歉,这太牵强了。如果你对编程很认真,你需要更加努力。
    • 我需要乘以不同的值而不是 2.9 我需要 2.1 而不是 4.227 我需要 4.0
    【解决方案2】:

    如果您无法使用其他答案,这里是另一个版本:

    awk -vval=2.1 '{              # set "val" to the new value for column 3 on first two lines
      if(NR==1 || NR==2) {        # if it's the first or second line
        $3=val;                   # set column 3 to val
        $2=$3*2.9                 # set column 2 to column 3 multiplied with 2.9
      } else if(NR>=3 && NR<=5) { # else if it's line 3-5
        $3=val+0.2;               # set column 3 to val+0.2
        $2=$3*4.227               # set column 2 to column 3 multiplied with 4.227
      } else $3=$3;               # just for formatting
      print                       # print the result
    }' test_file
    

    在运行之前删除 cmets (#)。

    输出:

    0.00 6.09 2.1 5.0 6.0 8.0 0.0
    10.00 6.09 2.1 1.0 1.0 1.2 9.6
    10.00 9.7221 2.3 2.0 1.4 2.5 9.6
    30.00 9.7221 2.3 1.2 1.5 1.9 1.4
    30.00 9.7221 2.3 3.2 2.4 1.2 4.1
    60.00 9.8 3.5 1.4 2.7 3.2 4.5
    

    要遍历一个范围并将其保存在不同的文件中,您可以执行如下操作。我还提供了其他参数,以便您可以在运行脚本时设置它们:

    #!/bin/bash
    
    for val in $(seq 2.1 0.1 2.5)
    do
      awk -vval=$val -vfmul=2.9 -vadd=0.2 -vsmul=4.227 '{
        if(NR==1 || NR==2) {
          $3=val;
          $2=$3*fmul
        } else if(NR>=3 && NR<=5) {
          $3=val+add;
          $2=$3*smul
        } else $3=$3;
        print
      }' test_file > output$val
    done
    

    【讨论】:

    • 你真的是个专家……谢谢你的支持……我在这里接受你的回答……很容易理解
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-24
    • 1970-01-01
    • 2021-03-30
    相关资源
    最近更新 更多