以下来源于一个很棒的群的聊天记录,整理成shell学习笔记(问题收集)……
1.bash版本引起的正则匹配问题
问题:
market_admin_131_142:~/decli/test # [[ $a =~ "[0-9]+" ]] && echo "---"
---
market_admin_131_142:~/decli/test # [[ $a =~ [0-9]+ ]] && echo "---"
---
market_admin_131_142:~/decli/test # echo $a
123a
这个怎么也匹配上了?
以上bash版本:
market_admin_131_142:~/decli/test # bash --version
GNU bash, version 3.1.17(1)-release (i586-suse-linux)
答案:
10:57:35#tp#~> [[ 123 =~ [0-9]+ ]]&&echo abc
abc
11:00:43#tp#~> [[ 123 =~ "[0-9]+" ]]&&echo abc
11:00:48#tp#~> [[ [0-9]+ =~ "[0-9]+" ]]&&echo abc
abc
11:00:56#tp#~>
加双引号后里面就是普通字符了,不是正则,你的版本应该是加双引号也当正则处理的
------------------------------------------------------------------------------
2.find命令参数过长问题
问题:
./A.MD Free Shrink.png
./Search.png
./VariablySFW.png
./Meebo.png
: No such file or directory
market_admin_131_142:~/decli/test # find -name "*.png" |xargs -0 ls -l
这个怎么也会报错
答案:
如果path目录(此处是当前目录)下文件过多就会因为“参数列表过长”而报错无法执行,而xargs即是一条用来将参数列表转换成小块分段传递给其它命令的unix命令,以避免参数列表过长问题。
例如,下面的命令:
rm `find /path -type f`
如果path目录下文件过多就会因为“参数列表过长”而报错无法执行。但改用xargs以后,问题即获解决。
find /path -type f -print0 | xargs -0 rm
因为unix filenames能够包含空格和换行,xargs的默认行为通常可能产生问题,包含空格、斜线、和换行符(newlines) 的文件名将被xargs错误的处理。在这种情况下,
可以用-0选项代替来防止此类问题。当使用该选项时,你必须确保处理xargs输入的程序也是使用null字符作为分隔符。例如如果是GNU的find命令,它的-print0选项可以为
你做到这项工作(使用null字符分隔)
find -name "*.png" -print0 | xargs -0 ls -l
------------------------------------------------------------------------------
3.bash的特性,间接引用
问题:echo ${!1}这个谁帮我解释一下
答案:间接引用,例如:
snowdrop@ubuntu:~$ tmpVar="date"
snowdrop@ubuntu:~$ newVar="tmpVar"
snowdrop@ubuntu:~$ echo $newVar
tmpVar
snowdrop@ubuntu:~$ echo ${!newVar}
date
用eval改写为:
snowdrop@ubuntu:~$ tmpVar="date"
snowdrop@ubuntu:~$ newVar="tmpVar"
snowdrop@ubuntu:~$ eval "echo \$newVar"
tmpVar
snowdrop@ubuntu:~$ eval "echo $newVar"
tmpVar
snowdrop@ubuntu:~$ eval "echo \$$newVar"
date
snowdrop@ubuntu:~$
例2:
17:14:19#tp#~> a=b;b=c
17:16:13#tp#~> echo ${!a}
c
17:16:17#tp#~>
以上用法类似eval的用法:
eval與脫逃字元
eval可以拿來執行一個命令,不過他最常用的是拿來作兩次變數的代換, 主要是每次執行一個shell 命令他會先evaluate一次,看到有$這個東西的就把值換一次把變數換掉, 然後再執行一遍。這種double scan的方法對一些變數代換很有用, 因為eval不是喚起另一個shell來執行,而是在本來這個shell內多evaluate一次, 所以代換結果可以保留下來。 例如如果我們要兩次代換
count=1
var1=I
var2=am
var3=a
var4=gyoza
while [ $count -lt 5 ]; do
eval "echo \$var$count"
let 'count=count + 1'
done
count可以一直變化1. 2. 3 ....要產生一個新變數var1 var2 var3....然後再對 var1 var2取值。其中因為第一個var不想被運算,所以先用escape字元\, 然後第二次運算時才被解釋。 那如果要三次以上變數代換在一行內解決呢? 想想看吧。
eval主要還用來evaluate執行一個shell script檔,可以像C一樣寫成很多的 模組shell script在同一個shell下run,則變數在此shell內通通有效。
$ eval ". foo.sh"
不過如果變數太多,名字會打架。
--------------------------------------------------------------------
4.tar命令打包是排除目标目录中的某些内容
问题:
$ tar -czvf css.tar.gz css/
css/
css/bind_sns.css
css/movie.css
.............
css/admin/.svn/
css/admin/.svn/text-base/
css/admin/.svn/text-base/wysiwyg.css.svn-base
css/admin/.svn/text-base/article.css.svn-base
css/admin/.svn/text-base/layout.css.svn-base
.............
css/.svn/
css/.svn/text-base/
css/.svn/text-base/news.css.svn-base
css/.svn/text-base/vip_payment.css.svn-base
css/live_content.css
css/vip.css
snowdrop@ubuntu:/var/www/vhosts/icn_web/public$ ls
css css.tar.gz editable_PNG images jscript template_instructions themes
请教下是否可以不打包css/下的.svn目录及其内部子目录内容
答案:
tar -czvf css.tar.gz css/ --exclude=".svn*"
------------------------------------------------------------------------
5.sed替换字符时对于'('和')'的处理
问题:请教一下,如果需要把index.php中所有出现$row['video_name']的地方都替换成cut_string($row['video_name'],20)的话,怎么处理这个'('和')'的问题,即便是使用escape符转意,也会被用来保存匹配的字符
答案:
10:24:00#tp#~> echo 'ab'|sed 's/.*/def(&)/'
def(ab)
10:24:07#tp#~>
echo "\$row['video_name']"|sed "s/\$row\['video_name'\]/cut_string(&,20)/"
-------------------------------------------------------------------------
6.awk如何输出连续的某些字段
问题:假如每行拥有的字段数都不确定,但字段数最少为10,我想打印从第10个字段到行末尾的内容,怎么做?
17:11:11#tp#test> echo 1 2 3 4 5 6 7 8 9|awk '{for(i=4;i<7;i++)printf $i" "}';echo
4 5 6
17:11:23#tp#test>
-------------------------------------------------------------------------
7.问题:sed怎么筛选一行中既有 aaa 又有 bbb 字符串?
答案:sed -n '/aaa/{/bbb/p}'
----------------------------------------------------------
8.关于nohup方式运行脚本或命令
问题:
jboss启动方式
run.sh -b 127.0.0.1 &
run.sh -b 0.0.0.0 &
二者何区别啊?
还有加nohup 和不加nohup区别
nohup run.sh -b 127.0.0.1 &
run.sh -b 127.0.0.1 &
答案:
127.0.0.1 是本机地址,0.0.0.0是所有地址
nohup 的作用是让进程忽略hangups信号用的
扩展:
比如ssh登录过去,运行完了run.sh -b 127.0.0.1 &
然后exit或logout退出这个ssh登录,这样jboss进程是不是就结束了啊
是不是得nohup run.sh -b 127.0.0.1 &
退出才不会导致jboss结束
答:不一定, 这和你的shell设置有关,和jboss本身的实现也有关,一般来说,是会结束
man bash
然后搜索huponexit
bash的配置文件(局部)各用户家目录下的.bashrc中可以查看配置了哪些shell options
bash的配置文件(全局)/etc/profile /etc/bash.bashrc
------------------------------------------------------------------
9.var=${str=expr}这句怎么理解,本来以为等价于str=expr;var=${str}这两句,但貌似不是……看shell十三问没看懂?在unset str前提下,是等价那两句的,但在str=(null值)前提下又不等价,哪位大哥帮忙解释下……
答案:只有在str这个variable是unset的情况下,才执行str=expr,否则无论str为null还是not null,都不执行str=expr;
标准答案:${parameter=default} -- 如果变量parameter没声明, 那么就把它的值设为default.比较全的就查下man bash里的 Parameter Expansion一节,ABS(Advanced bash tutorial)里头也解释的很明白,另外shell十三问稍后面的部分也解释的很明白
***************************************
var=${str=expr}
$str变量未定义时 $var值才为expr
***************************************
$str一但定义了,不论其是否为空,$var都== $str
****************
unset var
unset str
var=${str=expr}
此时$var值为expr
****************
unset var
str=
var=${str=expr}
此时$var也为空
****************
补充:查看变量var是否已经set方法(snowdrop@ubuntu:~$ set | grep ^var),用来区分unset和null的
---------------------------------------------------------------------
10.请教下如何将脚本中for循环里头的echo "svn delete file:///svn/jscn/$i -m 'delete file'"这一句送往/bin/bash执行啊?
答:| /bin/bash 或者去掉echo
例:vi for_demo.sh
#!/bin/bash
for i in `svn list file:///svn/jscn | grep '.html$'`
do
echo "svn delete file:///svn/jscn/$i -m 'delete file' " | /bin/bash
#svn delete file:///svn/jscn/$i -m 'delete file' #未测试
done