1.变量两边加双引号,保证原内容的格式
如果变量两边不加双引号的话,所有的多个空格被一个空格代替,所有的换行被删除
举例:
# a=`ls -l`
# echo $a
total 824 -rw-r--r-- 1 root root 878 Oct 10 18:10 1.txt -rw-r--r-- 1 root root 33083 Sep 22 16:41 a -rw-r--r-- 1 root root 29309 Sep 24 16:03 b -rw-r--r-- 1 root root 581 Oct 10 17:29 check_lockbox_timeout.sh -rwxr-xr-x 1 root root 721 Sep 24 15:55 check.sh -rw-r--r-- 1 root root 42439 Sep 22 16:32 hostgroup_name.txt -rw-r--r-- 1 root root 49948 Sep 22 16:32 host_name.txt -rw-r--r-- 1 root root 43051 Sep 24 15:55 host.txt -rw-r--r-- 1 root root 15 Oct 11 11:41 ip_list.txt -rw-r--r-- 1 root root 0 Oct 10 17:27 lockbox.log -rw-r--r-- 1 root root 289489 Sep 22 10:51 services.cfg -rw-r--r-- 1 root root 248472 Sep 24 15:55 services.cfg_1 -rw-r--r-- 1 root root 63405 Sep 24 15:55 services.cfg_2 drwxr-xr-x 2 root root 4096 Oct 11 11:06 StrictHostKeyChecking=no -rw-r--r-- 1 root root 117 Oct 14 15:59 test.sh
# echo "$a"
total 824
-rw-r--r-- 1 root root 878 Oct 10 18:10 1.txt
-rw-r--r-- 1 root root 33083 Sep 22 16:41 a
-rw-r--r-- 1 root root 29309 Sep 24 16:03 b
-rw-r--r-- 1 root root 581 Oct 10 17:29 check_lockbox_timeout.sh
-rwxr-xr-x 1 root root 721 Sep 24 15:55 check.sh
-rw-r--r-- 1 root root 42439 Sep 22 16:32 hostgroup_name.txt
-rw-r--r-- 1 root root 49948 Sep 22 16:32 host_name.txt
-rw-r--r-- 1 root root 43051 Sep 24 15:55 host.txt
-rw-r--r-- 1 root root 15 Oct 11 11:41 ip_list.txt
-rw-r--r-- 1 root root 0 Oct 10 17:27 lockbox.log
-rw-r--r-- 1 root root 289489 Sep 22 10:51 services.cfg
-rw-r--r-- 1 root root 248472 Sep 24 15:55 services.cfg_1
-rw-r--r-- 1 root root 63405 Sep 24 15:55 services.cfg_2
drwxr-xr-x 2 root root 4096 Oct 11 11:06 StrictHostKeyChecking=no
-rw-r--r-- 1 root root 117 Oct 14 15:59 test.sh
可以看出echo $a输入的时候,每个文件和目录都粘连在一起了(空格分隔),格式乱掉了。
2.复制隐藏文件
把/root/下的文件复制到/mnt/root到
cp -a /root/. /mnt/root #就是把*换成.就可以了
3.while中使用ssh就循环一次结束的问题
文本每一行包含一个IP在while循环中使用ssh,但ssh完第一行后就退出了,
while read line
do
ssh $line ls
done < ip.txt
但是使用for的时候就不存在这个问题,
原因: while中使用重定向机制,文件中的信息都已经读入并重定向给了整个while语句,所以当我们在while循环中再一次调用read语句,就会读取到下一条记录。问题就出在这里,ssh语句正好回读取输入中的所有东西(也就是把剩余文本里的东西都读进去了). 当read第二次循环的时候。文件文件已经结束了。while退出。
使用下面这个Shell可以证明这个问题:
while read line
do
ssh $line cat
done < ip.txt
解决办法:
- 使用ssh -n "command"
- ssh "cmd" < /dev/null # 将ssh 的输入重定向输入。
4.find xargs结合cp或者mv的使用方法
find 出来的文件要cp或者mv 的话,可以使用find 的exec
find /tmp -name "*.txt" -exec cp {} /data/ \;
find结合xargs使用的时候,cp 或者mv文件的方法如下:
find /tmp -name "*.txt" | xargs -I {} cp {} /data/ 或者
find /tmp -name "*.txt" | xargs -i cp {} /data/
-i 表示 find 传递给xargs的结果 由{}来代替
-I 必须指定替换字符. xarg的man页中表示废弃-i参数。建议使用-I{}来代替
find xargs 结合cp 或mv 的时候,另外一种方法
find /tmp -name "*.txt" | xargs cp -t /data/
find /tmp -name "*.txt" | xargs mv -t /data/
cp和mv 的 -t 参数是指定目标目录。此时目标目录在前,源文件在后\
5.bash shell中获取字符串的长度
-
使用wc:
wc -L可以获取到当前行的长度,因此对于单独行的字符串可以用这个简单的方法获取,另外wc -l则是获取当前字符串内容的行数。# echo "abc" |wc -L
-
使用expr
使用expr length可以获取string的长度# expr length "abc"
-
使用awk
通过awk+length的方式获取字符串长度
# echo “abc”|awk '{print length($0)}'
- 使用 echo \${#string} 的方式
注意:这里的string是该字符串的变量名name="abc" echo ${#name}
6.获取字符串的开头或最后的一个字符
- 变量截取
# a=3234j35ja
# echo ${a::1} # 获取开头的第一个字符
3
# echo ${a: -1} #获取最后的一个字符,注意-1前面有个空格, 但是 echo ${a: -100} ,如果越界的话,就获取到空字符。这一点需要注意,
a
- 使用cut
# a=3234j35ja
# echo $a | cut -c 1 #获取开头的第一个字符
3
# echo $a | cut -c $((${#a})) #获取最后的一个字符
a
- 使用sed
# a=3234j35ja
# echo "$a" | sed -e "s/^\(.\).*$/\1/" #获取开头的一个字符
3
# echo "$a" | sed -e "s/^.*\(.\)$/\1/" #获取最后的一个字符
a
- 使用awk
# a=3234j35ja
# echo "$a" | awk '{print substr($0,1,1)}' #获取开头的一个字符 ,substr(str,start,length)
3
# echo "$a" | awk '{print substr($0,length($0))}' #获取最后的一个字符, substr(str,start)
a
- 使用tail或head
# a=3234j35ja
# echo "$a" | head -c 1 #获取开头的一个字符
3
# echo $a | tail -c 2 # 获取结尾的一个字符,tail -c 1 是结束符
a
7.删除字符串开头或结尾的一个字符
- 字符串截取
# a=3234j35ja
# echo ${a%?} #删除结尾的一个字符
3234j35j
# echo ${a#?} #删除开头的一个字符
234j35ja
- 使用cut
# a=3234j35ja
# echo $a | cut -c 2- #删除开头的第一个字符
234j35ja
# echo $a | cut -c 1-$((${#a} -1)) #删除最后的一个字符
3234j35j
- 使用sed
# a=3234j35ja
# echo "$a" | sed -e "s/^.//" #删除开头的第一个字符
234j35ja
# echo "$a" | sed -e "s/.$//" #删除最后的一个字符
3234j35j
- 使用awk
# a=3234j35ja
# echo "$a" | awk '{print substr($0,2)}' #删除开头的第一个字符
234j35ja
# echo "$a" | awk '{print substr($0,1,length($0)-1)}' #删除最后的一个字符
3234j35j
- 使用tail或head
# a=3234j35ja
# echo "$a" | tail -c +2 #删除开头的第一个字符 ,+2表示从第2个字符开始显示
234j35ja
# echo "$a" | head -c -2 #删除最后的一个字符, -2表示显示到倒数第2个字符
3234j35j
8.shell函数返回一个字符串
function test() {
return "${1} abc"
}
out=test "${1}"
echo "....${out}"
直接return是会报错的, return只能返回一个数字,来表示命令是否执行成功。
解决办法:
function test() {
echo "${1} abc"
}
out=$(test "${1}") #把test函数的标准输出,赋值给变量out
echo "....${out}"
执行结果
# sh 1.sh 11111
....11111 abc
9.修改纳秒级的文件时间
之前用touch命令修改文件时间,只是精确到秒,有些特殊情况还是需要把文件时间修改的更精确一点
- 设置文件的访问时间和修改时间
# touch -d "2015-5-19 01:12:40.111000000" 1.txt
# stat 1.txt
File: `1.txt'
Size: 7 Blocks: 8 IO Block: 4096 regular file
Device: 803h/2051d Inode: 2228580 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-05-19 01:12:40.111000000 +0800
Modify: 2015-05-19 01:12:40.111000000 +0800
Change: 2015-5-19 14:50:08.035977483 +0800
- 设置文件的修改时间
# touch -m -d "2015-5-19 01:12:40.111000000" 1.txt
# stat 1.txt
File: `1.txt'
Size: 7 Blocks: 8 IO Block: 4096 regular file
Device: 803h/2051d Inode: 2228580 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-05-19 01:12:40.111000000 +0800
Modify: 2015-5-19 12:12:12.110000000 +0800
Change: 2015-5-19 14:50:08.035977483 +0800
把-m 改成-a 就是设置文件的访问时间了