252010

http://hi.baidu.com/test/blog/item/16ecf01f6f46e4f7e0fe0b10.html

当while read 遇上ssh
2007-08-15 21:13先看一段简化过的BASH SHELL代码

TODAY=`date +%Y%m%d`
SUFFIX="tar"
CONF=the_config_file
i=0

while read HOST SRCPATH DSTPATH
do
(( i++ ))
if [ "X${HOST:0:1}" = "X#" -o ${#DSTPATH} -eq 0 ]
then
#忽略注释行及少于3个项的记录
else
ssh ${HOST} "tar c ${SRCPATH}" >${DSTPATH}.${TODAY}.${SUFFIX} 2>/dev/null
fi
done < $CONF

作者的本意是通过脚本读取配置文件$CONF,然后打包备份$CONF中指定的文件,但执行后发现程序在成功备份$CONF中指定的第一个文件后即退出……

跟踪后发现read在备份完第一个文件后就再读不到任何数据,所以while循环结束--也就是说,
通过重定向$CONF文件传给标准输入的数据被

ssh ${HOST} "tar c ${SRCPATH}" >${DSTPATH}.${TODAY}.${SUFFIX} 2>/dev/null

这个命令提前吃掉了。

将其改为
ssh ${HOST} "tar c ${SRCPATH}" >${DSTPATH}.${TODAY}.${SUFFIX} 2>/dev/null </dev/null

将ssh的标准输入重定向到/dev/null,程序正常备份所有$CONF中指定的文件。

Posted by admin Tagged with: ,
252010

while read line的一些问题

Q1. 曾经面试的时候被问到一个问题, 说
while read line ; do
echo $line ;
done < ./a.txt
失败, 会是什么原因, 当时觉得不太可能, 就回答了“我用的时候没有碰到过这种情况”。 前段在写一个脚本的时候, 确实遇到了所谓的while read 失败, 原因是我读入的文件是在win下用dos格式保存的文本, 所以每行结束都带有一个\r字符, 这个字符在linux/unix环境下的作用是“回到一行的开始”, 如果再对$line做相关的字符串操作的话(比如字符串连接), 得到的结果可能会让人迷惑... 所以当把win下编译的文本用在linux/unix环境时, 最好做一下格式转换

Q2. 2009-08-01更新:
# cat ur_file
1234 abcd
5678 efgh

# vi t3.sh
#!/bin/bash

while read t1 t2 ; do
echo $t1 $t2 ; awk '{ print $0 }'
done < ./ur_file

#./t3.sh
1234 abcd
5678 efgh

# sh -x ./t3.sh 发现只read 了一次

Q3.

# seq 10 > file
# while read line ; do
> echo $line
> dd &>/dev/null
> done < ./file
1

为什么这里只打印第一行呢?
问题的关键在于:
read从输入读取了一行内容后,
其它的程序(比如 rsh或sed)从同样的地方把其它的输入读走了,
read当然读不到其它内容了,
while也就结束了

摘自:http://bbs.chinaunix.net/viewthread.php?tid=769040&extra=&page=2

可以打开set -x, 看看, 确实只read了两次, 第一次read出第一行, 第二次read不到就退出while循环
read 和 dd都从文件描述符3中读取数据

Posted by admin Tagged with: ,
082010

echo "newpasswd" | passwd user --stdin

Posted by admin Tagged with: ,
十二 152009

最近在阅读一个比较经典的关于shell的faq,全文链接在这里http://home.comcast.net/~j.p.h/

作者将comp.unix.shell新闻组上的常见问题总结了一下,做成faq的形式,对学习很有帮助。

不打算全文翻译了,仅把认为比较重要的部分总结一下,做个备案吧

1.UUOC(useless use of cat)

避免 cat file | tr -d ‘xyz’ ,因为这样实际上跑了两个进程cat 和 tr

应该采用输入重定向 tr -d ‘xyz’ <file

2.shebang

脚本第一行是告诉操作系统解释器路径的,如果用解释器显式调用脚本文件,

那么第一行只是注释而已,可有可无。

3.echo 在不同的shell里的解释方式可能不同,要熟悉你的shell是如何做的。

优先采用cat输出变量

cat<<EOF

$a

EOF

4.随机数生成方法

最portable的方法是利用awk内置的srand和rand函数

awk ‘BEGIN {srand();print rand()}’

5.dos和unix文本文件之间转换

dos格式的文本文件,行末尾是
(CR LF)

unix格式的文本文件,行末尾是

所以dos格式文本在unix下显式的时候,尾部会多一个^M

二者转换方式是

dos—unix : sed ’s/^M$//’ dos.txt > unix.txt或者tr -d ‘
‘ <dosfile >unixfile

unix—dos: sed ’s/$/^M/’ unix.txt >dos.txt

另外,也可以用dos2unix unix2dos等现成工具

6.改变term窗口的标题

两种方法

$ echo -en “33]2;XXX07″

$ printf ‘%b’ ‘e]2;XXXa’

7.如何设定用户输入超时

bash里面可以用read的参数-t 设置超时

也可以利用终端属性完成

{

s=$(stty -g)

stty -icanon min 0 time 100

var=$(head -n 1)

stty “$s”

}

8. bash脚本一定要注意空格的使用

$ [ -f xxx ] isn’t the same as

$ [-f xxx ]

9.如何从路径中分离目录和文件

pathname=’/path/to/some/file’

dir=`dirname “$pathname”`

file=`basename “$pathname”`

缺点是,fork出了新进程

可以使用shell内置的字符串处理机制

pathname=/path/to/some/file

file=${pathname##*/}

case $pathname in

*/*) dir=${pathname%/*};;

*) dir=”

esac

10.如何删除特殊字符开头的文件

例如删除 -foo,有三种方法

rm -foo

rm — -foo

rm -i — * (进入交互模式,提示动作)

转载自:http://www.oolec.com/compunixshell-faq-study-note/

Posted by admin Tagged with: ,
十二 112009

在进行文本处理的时候,我们经常遇到要删除重复行的情况。那怎么解决呢?
下面就是三种常见方法?
第一,用sort+uniq,注意,单纯uniq是不行的。
shell> sort file | uniq

这里我做了个简单的测试,当file中的重复行不再一起的时候,uniq将服务删除所有的重复行。经过排序后,所有相同的行都在相邻,因此unqi可以正常删除重复行。

第二,用sort+awk命令,注意,单纯awk同样不行,原因同上。
shell> sort file | awk '{if ($0!=line) print;line=$0}'

当然,自己把管道后面的代码重新设计一下,可能不需要sort命令先排序拉。

第三,用sort+sed命令,同样需要sort命令先排序。
shell> sort file | sed '$!N; /^\(.*\)\n\1$/!P; D'

最后附一个必须先用sort排序的文本的例子,当然,这个需要用sort排序的原因是很简单,就是后面算法设计的时候的“局部性”,相同的行可能分散出现在不同的区域,一旦有新的相同行出现,那么前面的已经出现的记录就被覆盖了,看了这个例子就好理解拉。
ffffffffffffffffff
ffffffffffffffffff
eeeeeeeeeeeeeeeeeeee
fffffffffffffffffff
eeeeeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeee
gggggggggggggggggggg

其实,这是我随便打进去的几行字,没想到就是必须用sort的很好例子,大家可以自己试试看。

参考资料:

[1] SED单行脚本快速参考

http://linux.chinaitlab.com/administer/381792.html

[2] 如何删除重复的行(sed或awk)

http://www.linuxsir.org/bbs/showthread.php?t=132848

转载自:http://www.91linux.com/html/article/shell/20090205/15636.html

Posted by admin Tagged with: ,