【问题标题】:export variable from awk从 awk 导出变量
【发布时间】:2014-04-05 22:35:24
【问题描述】:

我有这个相当简单的脚本

#!/bin/bash

awk -v channels=4096 '{for (i=1;i<=NF;i++) $i=$i-(i-1)*channels} END{printf "There are %d detectors\n ",detectors=NF;}1' $1.dat >$1_Processed.dat
rm -f $1.dat
printf "There are %d detectors\n",$detectors
exit 0

我要做的是打印 awk 读取的字段数(NF)。结果,变量detectors 总是得到0。

有没有办法解决这个问题?

编辑

完整的脚本是

#!/bin/bash

if test $1 ; then
   if [ -f $1.evnt ] ; then
      rm -f $1.dat
      sed -n '2p' $1.evnt | (read v1 v2 v3
      for filename in $1*.evnt ; do
         echo -e "Processing file $filename"
         sed '$d' < $filename > $1_tmp
         sed -i '/Kmax/d' $1_tmp
         sed -i '/^'"$v1"' '"$v2"' /d' $1_tmp
         cat $1_tmp >> $1.dat
      done
      v3=`wc -l $1.dat | awk '{print $1}' `
      echo -e "$v1 $v2 $v3" > .$1.dat
      rm -f $1_tmp)
   else
      echo -e "\a!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
      echo -e "  Event file $1.evnt doesn't exist  !!!!!!"
      echo -e "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
   fi   
else
   echo -e "\a!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
   echo -e "!!!!!  Give name for event files  !!!!!"
   echo -e "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
fi
detectors=$(awk -v channels=4096 '{for (i=1;i<=NF;i++) $i=$i-(i-1)*channels} END{print NF;}1' $1.dat >$1_Processed.dat)
#awk -v channels=4096 '{for (i=1;i<=NF;i++) $i=$i-(i-1)*channels} END{printf "There are %d detectors\n ",detectors=NF;}1' $1.dat >$1_Processed.dat
rm -f $1.dat
printf "There are %d detectors\n",$detectors
exit 0

一个典型的输入文件是

Kmax Event File - Text Format
1 6 1000 
1623 5730 8209 12307 16398 20495 
1505 5611 8208 12306 16395 20497 
934 5036 8208 12308 16399 20498 
1552 5656 8208 12306 16396 20495 
1622 5729 8208 12305 16397 20495 
1526 5631 8207 12305 16397 20496 
1522 5629 8208 12307 16396 20497 
1525 5630 8208 12306 16399 20496 
1625 5730 8208 12305 16396 20496 
1717 5822 8207 12305 16398 20495 
1690 5796 8209 12306 16397 20496 
1525 5630 8209 12305 16399 20495 
1625 5731 8208 12305 16397 20495 
1523 5629 8209 12307 16398 20497 
1719 5825 8208 12307 16398 20495 
1714 5821 8207 12305 16395 20496 
1525 5630 8208 12306 16399 20495 
1528 5634 8209 12306 16396 20496 
1624 5729 8208 12307 16397 20496 
1625 5729 8208 12305 16397 20495 
1524 5630 8209 12305 16397 20495 
1393 5497 8207 12306 16397 20495

【问题讨论】:

  • 请说明您希望 awk 脚本输出什么 - 您不能在其中进行所有数学运算,只是为了在最后打印 NF。此外,几乎可以肯定你的整个 shell 脚本可以更简洁地重写为 awk 脚本(shell 是从中调用工具的环境,而 awk 是处理文本文件的标准 UNIX 工具)所以如果你告诉我们整个脚本是什么旨在提供一些小而有代表性的样本输入和预期输出,我们可以帮助您。
  • 给定输入文件,检测器的数量是多少?在 END 块中,NF 是文件最后一条记录中的字段数。
  • 在较大的脚本中,$detectors 将始终为空:detectors=$(awk -v channels=4096 'blah blah blah' $1.dat &gt;$1_Processed.dat) -- 您将 awk 的输出重定向到文件,因此没有要为变量捕获的输出。
  • @glennjackman:在上述输入文件中,检测器的数量应该是 6 个。如何保留输出文件和变量?

标签: bash variables awk export


【解决方案1】:

你可能想要这个:

detectors=$(
    awk -v channels=4096 '
        {for (i=1;i<=NF;i++) $i=$i-(i-1)*channels; print} 
        END {print NF > "/dev/stderr"}
    ' $1.dat 2>&1 >$1_Processed.dat
)

重定向:

  • 首先,fd 2 被重定向到任何 fd 1 当前指向的位置
  • 然后 fd 1 被重定向到一个文件(这影响 fd 2 现在指向的内容)
  • 测试:

    $ x=$(awk 'BEGIN {print "stdout"; print "stderr" > "/dev/stderr"}' 2>&1 >/tmp/foo)
    $ echo "$x"
    stderr
    $ cat /tmp/foo
    stdout
    

print NF &gt; "/dev/stderr" 的形式可能特定于 GNU awk。

我注意到第2行的第2个字段也是6。如果这是检测器的数量,那么提取它是一种更明显的方法。

detectors=$( awk 'NR==2 {print $2; exit}' $1.dat )
# or
read a detectors b < <(sed -n '2{p;q}' $1.dat)

【讨论】:

  • 非常感谢您的回答!这真的节省了一天!非常感谢你的帮助!我想了解2&gt;&amp;1 做了什么,但恐怕我做不到!还有什么是“fd”?
  • fd 是“文件描述符”,它是一个表示打开文件的整数。 stdin 是文件描述符 0,stdout 是 fd 1,stderr 是 fd 2。在你的机器上,试试这个命令:ll -d /dev/{std*,fd}。在我的解决方案中,我需要将逐行输出发送到一个地方,END 打印输出另一个,所以awk的stdout被重定向到一个文件,stderr被重定向到stdout,所以变量可以抓住它。除了顺序很重要。
猜你喜欢
  • 1970-01-01
  • 2021-08-22
  • 2015-12-11
  • 2018-08-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-15
  • 1970-01-01
  • 2013-12-23
相关资源
最近更新 更多