日期:2014-05-16  浏览次数:20706 次

Linux Shell高级技巧(二)

七、非直接引用变量:

?? ?? 在Shell中提供了三种为标准(直接)变量赋值的方式:
?? ?? 1. 直接赋值。
?? ?? 2. 存储一个命令的输出。
?? ?? 3. 存储某类型计算的结果。
?? ?? 然而这三种方式都是给已知变量名的变量赋值,如name=Stephen。但是在有些情况下,变量名本身就是动态的,需要依照运行的结果来构造变量名,之后才是为该变量赋值。这种变量被成为动态变量,或非直接变量。
?? ?? /> cat > test7.sh
?? ?? #!/bin/sh
?? ?? work_dir=`pwd`
?? ?? #1. 由于变量名中不能存在反斜杠,因此这里需要将其替换为下划线。
?? ?? #2. work_dir和file_count两个变量的变量值用于构建动态变量的变量名。
?? ?? work_dir=`echo $work_dir | sed 's/\//_/g'`
?? ?? file_count=`ls | wc -l`
?? ?? #3. 输出work_dir和file_count两个变量的值,以便确认这里的输出结果和后面构建的命令名一致。
?? ?? echo "work_dir = " $work_dir
?? ?? echo "file_count = " $file_count
? ? ? #4. 通过eval命令进行评估,将变量名展开,如${work_dir}和$file_count,并用其值将其替换,如果不使用eval命令,将不会完成这些展开和替换的操作。最后为动态变量赋值。
? ? ? eval BASE${work_dir}_$file_count=$(ls $(pwd) | wc -l)
? ? ? #5. 先将echo命令后面用双引号扩住的部分进行展开和替换,由于是在双引号内,仅完成展开和替换操作即可。
? ? ? #6. echo命令后面的参数部分,先进行展开和替换,使其成为$BASE_root_test_1动态变量,之后在用该变量的值替换该变量本身作为结果输出。
? ? ? eval echo "BASE${work_dir}_$file_count = " '$BASE'${work_dir}_$file_count
? ? ? CTRL+D
?? ?? /> . ./test7.sh
? ? ? work_dir =? _root_test
? ? ? file_count =? 1
? ? ? BASE_root_test_1 = 1
???
八、在循环中使用管道的技巧:

?? ?? 在Bash Shell中,管道的最后一个命令都是在子Shell中执行的。这意味着在子Shell中赋值的变量对父Shell是无效的。所以当我们将管道输出传送到 一个循环结构,填入随后将要使用的变量,那么就会产生很多问题。一旦循环完成,其所依赖的变量就不存在了。
? ? ? /> cat > test8_1.sh
?? ?? #!/bin/sh
?? ?? #1. 先将ls -l命令的结果通过管道传给grep命令作为管道输入。
?? ?? #2. grep命令过滤掉包含total的行,之后再通过管道将数据传给while循环。
?? ?? #3. while read line命令从grep的输出中读取数据。注意,while是管道的最后一个命令,将在子Shell中运行。
?? ?? ls -l | grep -v total | while read line
?? ?? do
?? ? ?? ? #4. all变量是在while块内声明并赋值的。
??? ?? ?? all="$all $line"
?? ?? ??? echo $line
? ? ? done
? ? ? #5. 由于上面的all变量在while内声明并初始化,而while内的命令都是在子Shell中运行,包括all变量的赋值,因此该变量的值将不会传递到while块外,因为块外地命令是它的父Shell中执行。
? ? ? echo "all = " $all
? ? ? CTRL+D
? ? ? /> ./test8_1.sh
? ? ? -rw-r--r--.? 1 root root 193 Nov 24 11:25 outfile
? ? ? -rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh
? ? ? -rwxr-xr-x. 1 root root 108 Nov 24 12:48 test8_1.sh