分类: LINUX
2015-11-25 09:17:48
for i in `ls *.mp3`; do # Wrong!
for i in "`ls *.mp3`"; do # Wrong!
for i in *.mp3; do
cp "$file" "$target"
cp -- "$file" "$target"
for i in ./*.mp3; do cp "$i" /target ...
[ = "bar" ]
[ multiple words here = "bar" ]
[ "$foo" = bar ] # 几乎完美了。
[[ $foo = bar ]] # 正确
[ x"$foo" = xbar ] # 正确
[ bar = "$foo" ] # 正确
cd "`dirname "$f"`"
cd "$(dirname "$f")"
[ bar = "$foo" -a foo = "$bar" ] # Right! [ bar = "$foo" ] && [ foo = "$bar" ] # Also right! [[ $foo = bar && $bar = foo ]] # Also right!
(( $foo > 7 ))
[ $foo -gt 7 ]
[[ $foo -gt 7 ]]
grep foo bar | while read line; do ((count++)); done # 错误!
count=0
while read LINE
do
count=`expr $count + 1`
done < file
echo $count
问题是这个程序能得到什么样的结果?仿佛很明显,能够统计文件file的行数,然而你若执行一下便知,无论file的行数是多少,该程序的输出始终是0!为什么?
原来如果使用for,while,until,if,case这些命令时用到了重定向,那么sh会产生一个子shell来运行它们。可以想象count在循环体中能够正确的计数,一旦while执行完毕,子shell完成,其内部的变量count就消失了。因而得到的结果是循环体外开始赋的值0!
可以避免吗?试试这样:
cat file|while read LINE
do
count=`expr $count + 1`
done
echo $count
依然如此!怎么办?可以先关闭标准输入,然后以你要读取得文件重新打开它,这样就不需要对while命令的输入进行改向,也就不会用子shell的方式来运行它了。如下:exec
while read LINE
do
count=`expr $count + 1`
done
exec < /dev/tty
echo $count
也可以
exec 4<&0 0< file
count=0
while read LINE
do
count=`expr $count + 1`
done
exec 0<&4
echo $count
如果还有怀疑的话可以试一下if:
#!/bin/sh
echo "abcd"|if [ "abcd" = "abcd" ]; then
var=7
fi
echo $var
输出当然是空。去掉echo "abcd"|就好了。
所以不了解这一点在编程时就会非常危险,试想while,for,case,if,until是多么的常用,与管道或重定向连着用也是很常见的,可是一旦在其内部使用了什么变量,就是有进无出,有去无回了。
首先,exec 3<&0 0
然后,通过read命令读取name.txt的第一行内容line1,第二行内容line2,通过Exec 0<&3关闭文件描述符3;
最后,用echo命令输出line1和line2。最好在终端运行一下这个脚本,亲自尝试一下。
if grep foo myfile > /dev/null; then
if [ bar = "$foo" ]
if [ a = b ] && [ c = d ] # 正确
sed 's/foo/bar/g' file > tmpfile && mv tmpfile file
MSG="Please enter a file name of the form *.zip" echo $MSG # 错误!
Please enter a file name of the form freenfss.zip lw35nfss.zip
# This is wrong: echo <
su root -c 'some command'
-c, --commmand=COMMAND pass a single COMMAND to the shell with -c
cd /foo && bar
cd /foo || exit 1; bar baz
find ... -type d | while read subdir; do cd "$subdir" && whatever && ... && cd - done
find ... -type d | while read subdir; do (cd "$subdir" && whatever && ...) done
[ bar = "$foo" ] && echo yes [[ bar == $foo ]] && echo yes
for i in {1..10}; do ./something & done
$ ./dos -bash: ./dos: /bin/sh^M: bad interpreter: No such file or directory
-bash: !": event not found
$ echo "hi\!" hi\!
$ echo 'Hello, world!'
set +H echo "Hello, world!"
#!/bin/bash # Incorrect version for x in $*; do echo "parameter: '$x'" done $ ./myscript 'arg 1' arg2 arg3 parameter: 'arg' parameter: '1' parameter: 'arg2' parameter: 'arg3'
#!/bin/bash # Correct version for x in "$@"; do echo "parameter: '$x'" done $ ./myscript 'arg 1' arg2 arg3 parameter: 'arg 1' parameter: 'arg2' parameter: 'arg3'
* Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable. That is, "$*" is equivalent to "$1c$2c...", @ Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is, "$@" is equivalent to "$1" "$2" ...
foo() { ... }
25. netman shell13问笔记
shell执行过程: shell会依据IFS将command line所输入的文字扯为字段word,然后再针对特殊字符处理,最后重新组成command line IFS 由或 或 三者之一组成(我们常用 space ) ' 单引号内没有任何通配符、参数和变量替换,它阻止 shell 检查引号里面。$echo '$HOME' ,显示$HOME 。 " 双引号:除 Dollar signs($), Back quotes(``), Backslashes(\)外,所有内容留给应用解释,包括 IFS 和 CR 回车。 Backslash(\):相当于将跟随字符用单引号处理。 so awk '{print $0}'==awk "{print \$0}" ==awk \{print\ \$0\}