0%

Shell 读写数据

The read Command

read variable,执行此命令时,shell 从标准输入读取一行,并将第一个单词分配给变量中列出的第一个变量,将第二个单词分配给第二个变量,依此类推。如果该行上的单词多于列出的变量,则多余的单词将分配给最后一个变量。

read x y 从标准输入读入一行,把第一个单词保存到 x 中,其余的保存到 y 中,而 read text 则是把整行保存到 text 变量中。

A program to Copy Files

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if [ "$#" -ne 2 ]; then
echo "Usage: mycp from to"
exit 1
fi

from="$1"
to="$2"

if [ -e "$to" ]; then
echo "$to already exists; overwrite (yes/no)?"
read answer

if [ "$answer" != yes ]; then
echo "Copy not performed"
exit 0
fi
fi

Special echo Escape Characters

echo 会自动添加换行,可以使用 \c 来转义,\c 是由 echo 来处理的,而不是 shell,所以必须加引号,否则会被 shell 处理。

有些 shell 不能识别,书中说可以使用 /bin/echo,但是没起作用。

其他转义字符:

character prints
\b Backspace
\c The line without terminating newline
\f Formfeed
\n Newline
\r Carriage return
\t Tab
\\ Backslash chharacter
\0nnn ASCII 值为 nnn 的字符,其中 nnn 是一位到三位八进制数

An Improved Version of mycp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if [ "$#" -ne 2 ]; then
echo "Usage: mycp from to"
exit 1
fi

from="$1"
to="$2"

if [ -d "$to" ]; then
to="$to/$(basename $from)"
fi

if [ -e "$to" ]; then
echo "$to already exists; overwrite (yes/no)? \c"
read answer

if [ "$answer" != yes ]; then
echo "Copy not performed"
exit 0
fi
fi

cp $from $to

A Final Version of mycp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
numargs=$#
filelist=
copylist=

while [ "$#" -gt 1 ]; do
filelist="$filelist $1"
shift
done

to="$1"

if [ "$numargs" -lt 2 -o "$numargs" -gt 2 -a ! -d "$to" ]; then
echo "Usage: mycp file1 file2"
echo " mycp file(s) dir"
exit 1
fi

for form in $filelist; do
if [ -d "$to" ]; then
tofile="$to/$(basename $from)"
else
tofile="$to"
fi

if [ -e "$tofile" ]; then
echo "$tofile already exists; overwrite (yes/no)? \c"
read answer
if [ "$answer" = yes ]; then
copylist="$copylist $from"
fi
else
copylist="$copylist $from"
fi
done

if [ -n "$copylist" ]; then
cp $copylist $to
fi

The $$ Variable and Temporary Files

$$ 当前进程 ID,为了避免文件被破坏,可以在临时文件名上加上进程 ID

TMPFILE1=$(mktemp /tmp/im1.XXXXXX) 可以使用 mktemp

The Exit Status from read

除非遇到文件结束条件,否则 read 返回零退出状态。如果数据来自终端,则意味着用户按下了 Ctrl+d。如果数据来自文件,则意味着没有更多数据可从文件中读取。

1
2
3
4
5
# addi
while read n1 n2
do
echo $(( $n1 + $n2))
done
1
addi < data > sums

为每个文件增加行号。

1
2
3
4
5
6
7
8
9
# number 类似 nl 命令
lineno=1

cat $* |
while read line
do
echo "$lineno: $line"
lineno=$((lineno+1))
done
1
2
$ number phonebook
$ who | number

number 程序并不能很好的处理开头有很多空白字符和结尾有反斜线的行,可以使用 read -r line 处理结尾是反斜线的行,后面会介绍怎么处理开头是空白字符的行。

The printf Command

1
2
# printf "format" arg1 arg2 ...
printf "This is a number: %d\n" 10