【问题标题】:How to use bash variable inside the awk command substitution to assign another variable如何在 awk 命令替换中使用 bash 变量来分配另一个变量
【发布时间】:2021-06-02 19:41:25
【问题描述】:

我有 10 个文件名为

data_00
data_01
data_02
...
data_09

数据文件的前 8 行如下所示:

Stamp_number
10
Item_number
9000
Position
5.1008068168967009e+00 5.4899193183110690e+01
5.1008068168967009e+00 5.4899193183110690e+01
5.1008068168967009e+00 5.4899193183110690e+01

所有 10 个文件的格式相同,但所有数字的值不同。

我希望使用 awk 为 10 个文件的第 1 列和第 2 列的第 6 行、第 7 行和第 8 行的值分配一个 bash 变量,并得到它们之间的差异。

for i in {00..09}; do
a=$(awk 'NR==6 {print $1}' data_$i)
b=$(awk 'NR==6 {print $2}' data_$i)
c=$(awk 'NR==7 {print $1}' data_$i)
d=$(awk 'NR==7 {print $2}' data_$i)
e=$(awk 'NR==8 {print $1}' data_$i)
f=$(awk 'NR==8 {print $2}' data_$i) 
val_ab=`bc -l <<< "$a-$b"`
val_cd=`bc -l <<< "$c-$d"`
val_ef=`bc -l <<< "$e-$f"`
echo $val_ab
echo $val_cd
echo $val_ef
done

但这会打印 10 次以下语法错误:

(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
0.000000
0.000000
0.000000

我试过 data_"$i", data_[$i], data_${i} 但都失败了。如何在 awk 命令替换中使用 for 循环索引 i(或任何其他 bash 变量)来分配 bash 变量?

【问题讨论】:

  • 您的循环中的哪些命令确实产生了语法错误,i 的哪个值?您收到 6 条错误消息,循环执行了 100 次,而循环内只有 3 个从标准输入读取内容的命令。这在某种程度上不适合?
  • 我还建议您在进入循环之前添加一个echo using $BASH_VERSION,然后让我们知道您得到的结果。
  • @user1934428 它说使用 4.2.46(2)-release 我不知道错误的确切来源,但我的猜测是在命令替换中的 data_$i 中使用 i .
  • 这很容易找到!只需在启用set -x 的情况下运行您的程序,然后看看!如果我们甚至不知道它来自哪里,那么讨论一个错误是没有意义的。
  • @user1934428 感谢您告诉我。好吧,我看错了部分。这是 bc 行。

标签: bash awk


【解决方案1】:

bc 不支持科学计数法,但awk 支持

awk 'NR>=6 && NR<=8 {print $1-$2}' "data_$i"

【讨论】:

  • 此外,循环中笨拙而冗长的重复 Awk 调用真的非常恳求您将它们重构为像这样的单个 Awk 脚本。如果文件很大,可以通过在到达第 8 行时添加 exit 来优化。
  • 从您的示例中根本不清楚这是一项要求。可能会扩展 Awk 脚本以从循环内部完成剩余的处理;或者让 Awk 一次将所有九个打印到 Bash 数组中:result=($(awk 'NR &gt;=6 &amp;&amp; NR &lt;= 8 { print $1, $2, $1-2 } NR == 8 { exit }' "data_$i"))
  • @tripleee 感谢您告诉我。在您的示例中,我可以使用 result[1] ~ result[9] 处理数组“结果”的每 9 个元素吗?
  • Bash 数组是从零开始的,语法看起来略有不同。由于向后兼容的原因,它非常难看(记住 Bash 试图与 Bourne 兼容,所以 Bourne 之外的任何东西都需要使用在 Bourne shell 中并不意味着什么的语法。)第一个元素是${result[0]},最后一个是${result[8]}
  • @tripleee 谢谢。我可以在 bash 脚本中的 awk 或 sed 命令替换中使用 ${result[0]} ~ ${result[8]},就像 bash 脚本中的 awk 或 sed 中的其他 bash 变量一样?
【解决方案2】:

您可以在计算前将 E-notation 转换为10^,例如:

read a b c < <(tail -n3 data_00            |
               sed 's/e+\?/*10^/g; s/ /-/' |
               bc -l                       |
               tr '\n' ' ')
echo $a $b $c

输出:

-49.7983863662139891
-49.7983863662139891
-49.7983863662139891

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 2015-09-12
    相关资源
    最近更新 更多