【问题标题】:Bash: strange variable scoping issueBash:奇怪的变量范围问题
【发布时间】:2013-09-03 10:35:35
【问题描述】:

我正在编写一个简单的函数,它获取 /proc/[pid]/maps 的输出并将其写入 CSV。我想在底部写下所有地图的总大小。

函数如下:

output_MAPS ()
{

    {
    local total=0 
    echo "total , size , size_hex , start , end , perms , offset , dev , inode , path"
    echo "$1" | while read line ; do
        local start="$( echo "$line"| awk '{print $1}'| awk 'BEGIN { FS="-" } { print $1 }' )"
        local end="$( echo "$line"| awk '{print $1}'| awk 'BEGIN { FS="-" } { print $2 }' )"
        local perms="$( echo "$line"| awk '{print $2}' )"
        local offset="$( echo "$line"| awk '{print $3}' )"
        local dev="$( echo "$line"| awk '{print $4}' )"
        local inode="$( echo "$line"| awk '{print $5}' )"
        local path="$( echo "$line"| awk '{print $6}' )"
        local size=$(( 0x$end - 0x$start ))
        local size_hex="$( printf "%X" "$size")"
        local tot_size=$(( $tot_size + $size ))
        echo "$tot_size , $size , $size_hex , $start , $end , $perms , $offset , $dev , $inode , $path"
        total="$tot_size"
    done
    echo "TOTAL $total :: $tot_size" 
    }> "$outputdir/$4_$3_$2.csv"
}

这是最后几行输出:

114282496 , 20480 , 5000 , 2aaab14b0000 , 2aaab14b5000 , rw-p , 2aaab14b0000 , 00:00 , 0 ,
170688512 , 56406016 , 35CB000 , 2aaab14b5000 , 2aaab4a80000 , r--p , 00000000 , 08:02 , 3702398 , /usr/lib/locale/locale-archive
170717184 , 28672 , 7000 , 2aaab4a80000 , 2aaab4a87000 , r--s , 00000000 , 08:02 , 4000735 , /usr/lib64/gconv/gconv-modules.cache
170721280 , 4096 , 1000 , 2aaab4a87000 , 2aaab4a88000 , rw-p , 2aaab4a87000 , 00:00 , 0 ,
170811392 , 90112 , 16000 , 7ffffffe9000 , 7ffffffff000 , rw-p , 7ffffffe8000 , 00:00 , 0 , [stack]
179200000 , 8388608 , 800000 , ffffffffff600000 , ffffffffffe00000 , ---p , 00000000 , 00:00 , 0 , [vsyscall]
TOTAL 0 ::

我们可以从第一列中看到我正在计算总数,但我无法将值从循环中取出,即使我将它分配给外部声明的变量也是如此。 那我在做什么蠢事?

【问题讨论】:

  • 请注意,local 的工作方式并不像您期望的那样(尽管它不会影响您编写的代码)。一个变量只能是函数的局部变量;新作用域不是由命令组或while 循环等结构定义的。

标签: bash variables loops scope


【解决方案1】:

问题是您正在通过管道进入while 循环。循环在子shell中执行,当循环完成时,其中定义的所有变量都将被丢弃。这就是为什么你看到tot_size 是空白的。

使用重定向代替管道,如下所示:

while read line ; do
    local start="$( echo "$line"| awk '{print $1}'| awk 'BEGIN { FS="-" } { print $1 }' )"
    local end="$( echo "$line"| awk '{print $1}'| awk 'BEGIN { FS="-" } { print $2 }' )"
    local perms="$( echo "$line"| awk '{print $2}' )"
    local offset="$( echo "$line"| awk '{print $3}' )"
    local dev="$( echo "$line"| awk '{print $4}' )"
    local inode="$( echo "$line"| awk '{print $5}' )"
    local path="$( echo "$line"| awk '{print $6}' )"
    local size=$(( 0x$end - 0x$start ))
    local size_hex="$( printf "%X" "$size")"
    local tot_size=$(( $tot_size + $size ))
    echo "$tot_size , $size , $size_hex , $start , $end , $perms , $offset , $dev , $inode , $path"
    total="$tot_size"
done <<< "$1"

有关此问题的详细说明,请参阅:BashFAQ/024

【讨论】:

  • 哦!谢谢你:我没有意识到循环在子shell中。我喜欢学习东西:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-02
  • 2011-11-28
  • 2014-09-24
  • 1970-01-01
  • 2017-03-10
  • 2016-12-20
相关资源
最近更新 更多