1, 怎样处理用户名?(怎样从/etc/passwd中把用户目录读出来?)
引用 :
我在做一个自动设置输入法环境变量的脚本,因为是用 root 运行,所以我就想从 /etc/passwd 里把用户目录给读出来。现在的情况是这样:
[tram@~]$ sed -n '{s/^[^\/]*//;s/\:.*//;p}' /etc/passwd
/root
/home/tram
/home/kde
[tram@~]$
算是得到了每个用户的根目录,但是要怎样才能一个一个的设置呢?因为在运行前,是不知道有几个用户的,是不是能做一循环呢?谢谢!
解答参考 :
a,sed
代码 :
sed -n '{s/^[^\/]*//;s/\:.*//;p}' /etc/passwd
b,awk
代码 :
awk -F: '{print $6}' /etc/passws
c,cut
代码 :
cut -f6 -d: /etc/passwd
d,script
代码 :
#! /bin/bash
#showhome.sh
IFS=:
while read name pass uid gid gecos home shell
do
    echo $home
done
执行 ./showhome.sh < /etc/passwd

2, 如何将文本文件的每行做为字符串送入一个变量?
引用 :
就是对一行文本送入一个字符串变量,然后下一行再做同样动作,应该是个循坏。目标为了把想要下载的软件放在一个文本中,然后从另一个文本中找本上面这些软件包 REQUIRE 的其它包,然后生成一个下载列表,让 FTP 程序安刻列表自动去下载。
解答参考 :
引用 :
如果把一行文本送入一个字符串变量,可以采用直接赋值的方式。如:
AA= "This is a example"
如果要把 xxxx.txt 文件不同的行赋值给同一个变量,可以用 awk :
cat xxxx.txt | awk '{ AA = $0 }'
然后在 awk 内部加上对 AA 变量进行处理的函数。
其中将文件中每行赋给一个变量的方法为 :
代码 :
zhyfly@zhyfly:~/bash$ cat 1
xaAsdfasfABC...
21A32ABC...
xxxxABC...
zhyfly@zhyfly:~/bash$ cat 1|awk '{a[x++]=$0}END{for(i=0;i<NR;i++)print i,a[i]}'
0 xaAsdfasfABC...
1 21A32ABC...
2 xxxxABC...
zhyfly@zhyfly:~/bash$
3,如何把汉字变成类似"%AC%5B"的符号?
引用 :
我编 bash script 程序用 wget 下载文件,但有些文件名是中文的,必需把这些中文文件名写成这样的格式,如 "%AC%A1" 。怎样把汉字变成这样的编码呢?多谢!
解答参考 :( 利用 xxd,tr,sed 命令 )
引用 :
我倒是可以把汉字转成 encode 格式:
xie 0$ echo 论坛 | tr -d "\n" | xxd -i | sed -e "s/ 0x/%/g" | tr -d " ,\n"
%c2%db%cc%b3
大写的:
xie 0$ echo 论坛 | tr -d "\n" | xxd -i | sed -e "s/ 0x/%/g" | tr -d " ,\n" | tr "[a-f]" "[A-F]"
%C2%DB%CC%B3
不过这会把 url 中允许的正常字符一起编码,所以还要改成只转 url 中不允许的字符才行。
4,怎样将\n换成换行符??
引用 :
例如有文本如下:
abcd\nabcde
cdef\nmmmini
qqqmad\nnnnnnn

将 \n 换成换行符后应是:
abcd
abcde
cdef
mmmini
qqqmad
nnnnnn

如何做??
解答参考 :
a, 直接利用 sed
代码 :
zhyfly@zhyfly:~/bash$ cat escape
abcd\nabcde
cdef\nmmmini
qqqmad\nnnnnnn
zhyfly@zhyfly:~/bash$ cat escape|sed 's/\\n/\
> /g'
abcd
abcde
cdef
mmmini
qqqmad
nnnnnn
zhyfly@zhyfly:~/bash$
b,sed 后再利用 tr
代码 :
zhyfly@zhyfly:~/bash$ cat escape|sed 's/\\n/@/g'|tr '@' '\n'
5, 怎么替换行中的某一不确定字段??
引用 :
现有一文本文件 . 内容如下 :
/root/text #mysql
#KILL
/root/big #you
/root/ghg

/root/lll

' 用 Sed 命令 . 我可以删除 "#KILL" 和空行 .
但是在 /root/text 后面的 #mysql 和 /root/big 后面的 #you 这两个字段我怎么删除呢 ??
#mysql 和 #you 是不确定的字段 . 了就是说 # 后面可以跟任意的字段名称 , 而不一定是 mysql 和 you
感觉好像 SED 就是用来进行行操作的 .
解答参考 :
代码 :
zhyfly@zhyfly:~/bash$ cat mysql
/root/text #mysql
#KILL
/root/big #you
/root/ghg
 
/root/lll
zhyfly@zhyfly:~/bash$ sed 's/#.*//g' mysql # 还去掉空行的话就sed -e 's/#.*//g' -e '/^$/d' mysql
/root/text
 
/root/big
/root/ghg
 
/root/lll
zhyfly@zhyfly:~/bash$ sed 's/#.*//g' mysql
6,如何理解sed -e 's/^\([a-zA-Z]\+\) \([a-zA-Z]\+\)\(.*\)/\2 \1\3/g' file?
解答参考:
首先
引用 :
加号表示至少匹配一次。

\? 等表示引用前面的第 ? 个匹配 .
其次
引用 :
意思如下:
在文件每一行的开始,如果在第一个空格之前只含有英文字符,那么与空格之后的以英文字符开头截止到最后一个英文字符的字符串进行对换,例如
First Second1234....
变为 Second First1234....

后面的数字为替代符,顺序代表前面那三个括号里的表达式, 1 就是第一个括号里的内容,以此类推,那么原有顺序 \1 \2\3 就被替换为 \2 \1\3 ,所以就是一二表达式替换而已
7,如何删除换行符?
引用 :
我想将几行合并成一行如何删除换行符或回车符??
解答参考 :
a, 脚本 script
代码 :
#!/bin/bash
for i in `cat file`
do
echo -n $i
done
b,sed
代码 :
echo $(cat file)|sed 's/ //g'
c,tr
代码 :
cat 1|tr -d '\n';echo
8,如何求列最大值?
具体:
引用 :
除了逐行比较 , 还有什么办法么 ?
3q
有没有现成的 sh
解答参考 :
引用 :
代码 :
求tmp文件中第一列中最大值,tmp文件如下:
javalee//home/javalee/lx>cat tmp
12      343
534     3445
4       34
7765    3
44      5
9       9
3       59
845     576
2589    45
35      9.9
8i      123
3       3
2       3576
3       856
4       5
javalee//home/javalee/lx>cat tmp|awk '{print $1}'|sort -n|sed -n '$p'       # 执行
7765    # 结果
思路 : 用 awk 取 tmp 第一列数据 , 用 sort 排序之后 ( 由小到大 ), 用 sed 显示末行 ( 即排序后最大的数值 )
9,如何在AWK里面把数据添加到文件里?
引用 :
比如在 END 块里面把数组内容写到一个文件里面去。
解答参考 :
引用 :
javalee//home/javalee/lx>cat data
Mike Harrington:[510) 548-1278:250:100:175
Christian Dobbins:[408) 538-2358:155:90:201
Susan Dalsass:[206) 654-6279:250:60:50
Archie McNichol:[206) 548-1348:250:100:175
Jody Savage:[206) 548-1278:15:188:150
Guy Quigley:[916) 343-6410:250:100:175
Dan Savage:[406) 298-7744:450:300:275
Nancy McNeil:[206) 548-1278:250:80:75
John Goldenrod:[916) 348-4278:250:100:175
Chet Main:[510) 548-5258:50:95:135
Tom Savage:[408) 926-3456:250:168:200
Elizabeth Stachelin:[916) 440-1763:175:75:300
javalee//home/javalee/lx>awk -F: '{name[x++]=$1};END{for(i=0;i<NR;i++)print i,name[i]}' data >tmp # 取文件中 $1 域中的值作为数组 , 在输出到文件 tmp 中
javalee//home/javalee/lx>cat tmp
0 Mike Harrington
1 Christian Dobbins
2 Susan Dalsass
3 Archie McNichol
4 Jody Savage
5 Guy Quigley
6 Dan Savage
7 Nancy McNeil
8 John Goldenrod
9 Chet Main
10 Tom Savage
11 Elizabeth Stachelin
10,提取IP地址进入variable的问题
引用 :
我想写一个 function ,提取 IP 地址进入 variable 。但是看过 grep 和 sed 都好像还没有找到答案,用 awk 也不行,因为这一行字并不一定有这样的 field 格式。

例如
You are browsing from 122.39.123.153 -> 122.39.123.153
So you wanna access 172.20.199.23? -> 172.20.199.23

我现在停留在:
extract=$($source | sed -n '/\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\)/p')
11,怎么查找对属主用户可读的文件?
引用 :
关于 find 命令的问题 .
我发现 perm 选项要用三位数 , 比如 -perm 711 , 如果我不关心 group 和 others 的权限 , 即这个三位数的后两位可为任意数 , 而对 user 必须是可执行的 ( 也有可能可读 , 可写 ). 我该用什么选项呢 ?
或者我想找出 user 的权限位是 7, 而不关心 group 和 others 的权限 , 该用什么选项呢 ?
谢谢 .
解答参考 :
a,sed
代码 :
ls -l|sed -n '/^.rwx.*/p'
b,find+grep
代码 :
find . -exec ls -l {} \; |grep ^-rwx
12,如何快速把带有大写字母的文件名改为全部小写?
解答参考:
a,script
vi change_name
代码 :
#!/bin/bash
for f in *;do
mv $f `echo $f |tr "[A-Z]" "[a-z]"`
done
保存后在要转换的目录下执行
sh /path/to/change_name
b,rename
格式
代码 :
rename source_pattern target_pattern source_files
13,怎样在一个文件的特定的地方加入一点东西?
具体:
引用 :
比如我有一个文本文件的内容如下

# Multiple FontPath entries are allowed (they are concatenated together)
# By default, Red Hat 6.0 and later now use a font server independent of
# the X server to render fonts.
RgbPath "/usr/X11R6/lib/X11/rgb"
FontPath "unix/:7100"
EndSection

Section "Module"
Load "dbe"
Load "extmod"
Load "fbdevhw"
Load "glx"
Load "record"
Load "freetype"
Load "type1"
Load "dri"

现在我想在上面的红字的下面加入一行 FontPath "/usr/fonts"
那么在 shell 编程中应该如何操作呢?
还有我想在蓝字的前面加入一个 # 键又该如何操作呢?
解答参考 :sed 或者 awk
代码 :
cat add|sed -e '3a\FontPath "/uer/fonts"'
cat add|sed -e 's/Load "freetype"/#&/g'
14,怎样在一个文件中读一个值给变量?
引用 :
例如我有一个文件 line 的内容是 : 6 jor
现在我想提取里面的 6 给一个变量 loop 以供它用 .
读问怎么样实现 ?
在 SHELL 编程下 .
我试过 loop=more line 不行
loop=less line 也不行
解答参考 :
代码 :
read loop foo < line
echo $loop
15,请问:怎么读出文件中的内容并输出给scp调用?
引用 :
有一批 ip 地址的列表文件: 1.txt 、 2.txt 、 3.txt…… ,文件的内容如下:

$cat 1.txt

211.101.24.xxx
211.101.24.xx
211.100.25.xxx
211.100.25.xxx
...

其它的文件内容也类似,然后我希望实现一个 scp 操作,就是把某一个文件批量 scp 到一批服务器上,服务器 ip 列表从上述文件中的某一个读取
补充 :scp 是 ssh 的拷贝命令,用来在两台服务器之间拷贝文件,命令格式如下:
scp 源文件 目标服务器 ip :目的路径
举例如下:
$scp /home/guest/a 211.100.25.48:/etc/sysconfig/b.sh
这行命令将本机 /home/guest/ 下的文件 a 拷贝到远程机器 211.100.25.48 的 /etc/sysconfig/ 下,并命名成 b.sh
解答参考 : 利用 for 循环
代码 :
for i in $(cat 1.txt)
do
scp 源文件 $i 目标路径/文件
done
16,指点一下 shell中的 模板替换功能!
引用 :
我想实现一个用模板文件中域的替换功能:
讲不太清楚,看下面的例子:
templete.txt
------------------------------
Hello,<!--name-->!
where are you going?
I want to <!--where-->
------------------------------
以上是要使用的模板,其中有两个域: <!--name--> <!--where-->

我有两个变量: $NAME $WHERE
通过 sed 怎么 把这两变量提换到上面的域中,并且输出到标准输出中去?
解答参考 :
代码 :
cat templete.txt|sed -e 1s/\<.*\>/$NAME/g
17,sedawk练习!
引用 :
现有文本文件格式如下:
--------------------------------------------------------------------
#It's a configurefile

Section "SystemCheck"

Package:x-window-system-core
Package:wmaker
Package:locales
Package:defoma
Package:x-ttcidfont-conf
Package:libft-perl
Package:libgtk1.2-common
Package:xlibs-dev

EndSection

Section "SoftwareConfig"

Package:XMMS
Package:Gimp
Package:xchat

EndSection
--------------------------------------------------------------------
要求:将该文件中的两类 Package 分别读入变量 systemlist 和 softwarelist ,各 Package 名称之间以空格分隔。

即 echo $systemlist 的结果如下:
x-window-system-core wmaker locales defoma x-ttcidfont-conf libft-perl libgtk1.2-common xlibs-dev
解答参考 :
代码 :
systemlist=`cat sedawk|sed -n '/Section\ "SystemCheck"/,/EndSection/p'|awk -F: '{print $2}'`
or
代码 :
systemlist=$(cat sedawk | sed -ne '/Section "SystemCheck"/,/EndSection/s/\(.*\)Package:\(.*\)/\2/p')
18,如何截短一个字符串?
引用 :
做一个批量改名的脚本(练手),碰到一个问题

##########################
#!/bin/sh
#batch file for filename convertion

for file in `ls`
do
mv $file $file.txt
done
##########################

这是一个很简单的改名脚本,就是把 .txt 加到文件尾而已 .
如果要把一个文件名的后缀替换掉,比如
把 "001.rmvb" 改成 "001.rm"
那么怎么处理这个字符串,把 .rmvb 去掉呢 ?
解答参考 :
代码 :
ls|sed -e 's/^\(.*\)\.\(.*\)/\1/g'
另外截头去尾还可以使用
${variable#characters}
${variable##characters}
${variable%characters}
${variable%%characters}


19, 取值的问题?
引用 :
有一整数,格式为: 12345678 ,我想把 12 赋值给 A , 34 赋值给 B , 5678 赋值 C ,请问用什么命令可以实现?
解答参考 :
a,sed
代码 :
echo $s|sed 's/^\(..\)\(..\)\(.*\)$/\1 \2 \3/'
b,cut
代码 :
echo $s|cut -c1-2
echo $s|cut -c3-4
echo $s|cut -c5-8
c,echo ${}
代码 :
echo ${s:0:2}
echo ${s:2:2}
echo ${s:4:4}
20,格式转换shell的问题?
引用 :
1TRF
2PNI
2PDE
1EGR
1ATX
1EPS
1ERG
1PNH
1EFM
1POU
2AT2
1ERP
1BAL
1HPB
2CBH
1SIS
1GAT
7I1B
1CDB
4TRX
1CIS
1TPM
1TFI
2CRD
1HCC
现在想把每一行都变成 pdb+ 上面每一行内容 +.Z
例如本来是 1HCC 的变成 pdb1HCC.Z ,这个 shell 该怎么写啊?
解答参考 :
a,sed
代码 :
cat list|sed 's/\(.*\)/pdb\1\.Z/g'
b,
代码 :
for i in $(cat list);do echo "pdb$i.Z";done>tmp;rm list;mv tmp list
21,如何用shell去处文件里特定的行?
引用 :
例如
25%gfdghfhghgh

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

25%gfdkgjfkjgjkkk

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

25%agdfgdfgfdgg

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
我该怎么做才能把 25% 开始的那行和下面的一个空行去掉?
解答参考 :
a,sed
代码 :
cat tmp|sed -e '/^25%/d' -e '/^$/d'
b, 删除空行的方法 :
代码 :
sed '/^$/d' file
tr -s "\n" file
for i in $(cat file);do echo $i;done
22,sed替换功能中变量如何表示?
引用 :
脚本如下:
#!/bin/bash

IP1=`cat /tmp/ip1`
IP2=`cat /tmp/ip2`

sed -e 's/$IP1/$IP2/g' /tmp/test.txt

此脚本未把 /tmp/test.txt 文件中的包含 /tmp/ip1 的内容字符替换为 /tmp/ip2 中的字符
解答参考 :
代码 :
sed -e s/${IP1}/${IP2}/g /tmp/test.txt
23,怎么把大写子母转换成小写?
引用 :
pdb1TRF.ent.Z
pdb2PNI.ent.Z
Apdb2PDE.ent.Z
pZdb1EGR.ent.Z
pdb1ATX.ent.Z
pdb1EPS.ent.Z
pdb1ERG.ent.Z
pdb1PNH.ent.Z
pdb1EFM.ent.Z
pdb1POU.ent.Z
pdb2AT2.ent.Z
Zpdb1ERP.ent.Z
Zpdb1BAL.ent.Z
需要把里面除最后的 Z 以外的大写子母改成小写该怎么实现?
解答参考 :
a,sed
代码 :
cat tmp|tr A-Z a-z|sed 's/z$/Z/g'
b,
代码 :
for i in $(cat tmp|awk -F. '{print $1"."$2}');do echo "$(echo $i|tr A-Z a-z).Z";done
24,我要实现这个功能该怎么做?
引用 :
我的家目录有一个 Develop 目录
1. 我想将该目录下面的所有 java 文件选出
2. 找到作者是我的文件 (@author jimmy)
3. 最后在这些文件中搜索所有包含有 Hashmap 的行
( 当然也可以考虑直接将他改为 HashMap)

我是这么做的 ,
find /home/jimmy/Develop -name "*java*" -exec grep jimmy -l {} \;
这么做的结果是完成了前两步 . 输出如下
/home/jimmy/Develop/Users.java
/home/jimmy/Develop/Services.java
/home/jimmy/Develop/Status.java

我想使用 :
find /home/jimmy/Develop -name "*java*" -exec grep jimmy -l {} \; | grep Hashmap -n
却行不通
解答参考 :
代码 :
grep Hashmap -n `find /home/jimmy/Develop -exec grep jimmy -l {} \;`
代码 :
ls -l|grep username|find . -name "filename"|xargs grep -l "string"
代码 :
sed -ne 's/Hashmap/HashMap/gp' `find /home/jimmy/Develop -exec grep jimmy -l {} \;`
25,怎样转换以下文档??
引用 :
转换以下文档 :

Joey: What, like there's a rule or something?

(The door buzzer sounds and Chandler gets it.)

Chandler: Please don't do that again, it's a horrible sound.

Paul: (over the intercom) It's, uh, it's Paul.

Monica: Oh God, is it 6:30? Buzz him in!

Joey: Who's Paul?

转换成 :

{\bf Joey:} What, like there's a rule or something?

(The door buzzer sounds and Chandler gets it.)

{\bf Chandler:} Please don't do that again, it's a horrible sound.

{\bf Paul:} (over the intercom) It's, uh, it's Paul.

{\bf Monica:} Oh God, is it 6:30? Buzz him in!

{\bf Joey:} Who's Paul?
解答参考 :
代码 :
cat tmp|sed 's/^\([[:alpha:]]*:\)/{\\bf\ \1}/g'
26,请问如何统计一个文件中某个模式出现的次数??
解答参考:grep tr
代码 :
cat file|tr " " "\n"|grep -wc "matchpattern"
27,求一Shell能够将文本文件中以特定字符串搜索到的行和它的下一行显示出来。
解答参考:
a,sed
代码 :
sed -n '/pattern/{N;p}' file
b,grep
代码 :
grep -A1 'pattern' file
28,如何将一个输出中的若干行分别赋值给变量?
引用 :
比如一个命令输出里面有 3 行
a
bbb
ccccccc

分别赋值给变量 a1,a2,a3 ,可以么?如果输出更多,创建的变量也相应越多?

还有,如何读取一个文本文件中的若干行呢,和上面一样,分别赋值,可以么?
解答参考 :
代码 :
for i in $(cat file);do eval a$n=$i;((n+=1)); done
29,有一批文件,里面都有共同内容的一行文本,能编一个脚本,把它们都删除吗?
引用 :
是这样的,有一个学习 php4 的 .chm 格式的文件,因在 Linux 下无法看,我在 WIN 下用反编译工具保存为 *.html 格式。由于反编译工具未注册,这样生成的 *.html 文件里面都有一行提示,原文件内容如下 :
<br> This file is decompiled by an unregistered version of ChmDecompiler.<br> Regsitered version does not show this message. <br>You can download ChmDecompiler at : <a href="http://www.etextwizard.com/" target=_blank>http://www.etextwizard.com/</a><br><br>
我想把所有这些文件内的上述提示去掉,用脚本能做到吗,应怎样实现,还有更好的方法吗 ?
解答参考 :
scirpt:
代码 :
#!/bin/bash
for file in *.html
do
sed -e '/This file is decompiled/d' > temp
rm $file
mv temp $file
done
引用 :
sed '/aa/s/abc/arg/' filename
这个命令是用来替换文本的,但是我想问,如果在这条语句的前面有一个变量,我想用这个变量的值来替换文件中的满足条件的字符串,用 sed 如何来做?因为在单引号中的变量不能替换。
如果用 sed 不行,是否还有取代的办法?
解答参考 : 假设 arg 为变量
代码 :
sed /aa/s/abc/$arg/ filename
sed '/aa/s/abc/'$arg'/' filename
sed "/aa/s/abc/$arg/" filename
tr
代码 :
$var=newstr
$cat urfile|tr oldstr $var
 
31. 几种shell里的小括号,大括号结构和有括号的变量,命令的用法
在这里我想说的是几种 shell 里的小括号 , 大括号结构和有括号的变量,命令的用法,如下:
PHP 代码 :
1. ${var}
2. $( cmd )
3. () 和 {}
4. ${var:- string },${var:+ string },${var:= string },${var:? string }
5. $(( exp ))
6. $(var% pattern ),$(var%% pattern ),$(var #pattern),$(var##pattern) 

现在分述如下:
1.Shell 中变量的原形: ${var}
大家常见的变量形式都是 $var, 如
PHP 代码 :
$ var= test
$ echo  $var
test 

但当你要显示变量值加随意的字符 ( 我这里用 AA) 时,就会出错,如下:
PHP 代码 :
$ echo  $varAA



这时应该用变量的原形: ${var} ,即是加一个大括号来限定变量名称的范围,如下
PHP 代码 :
$ echo ${var} AA
testAA


以这个特性,我们可以很方便地写一个批量改后缀名的程序,我把它命名为 mymv ,程序如下:
PHP 代码 :
#!/bin/bash
 
tail =$ 1
for  filename in  ` ls `
do
    mv $filename  ${ filename }. $tail
done 

程序需要提供一个后缀名,如 c ,表示改为后缀为 c 的 C 程序文件,看下面的测试:
PHP 代码 :
$  ls
a b c
$  mymv c
$  ls
a . c b . c c . c


看样子程序运行的很好,但这是不完善的程序,有 2 个要注意的问题:
A, 目录下没有子目录,如果有一个目录,假设为 dir ,则也会被改为 dir.c ,这显然不是我们想要的,应该修正这个程序能识别目录。
B, 没有帮助对程序的参数进行处理,程序应该足够友好,在用户没有给定后缀名时应能处理,像上面的将直接给文件加上了一个点 (.), 这显然也不是我们想要的。

因为我们的目的是说明 ${var} ,这样已经足够了,因此这里不会再对上面的程序进行修正。

2. 命令替换 $(cmd)
命令替换 $(cmd) 和符号 `cmd`( 注意这不是单引号,在美式键盘上, ` 是 ESC 下面的那个键 ) 有相同之处
PHP 代码 :
$  ls
a b c
$ echo $( ls )
a b c
$ echo ` ls `
a b c 

我们来分析一下命令 echo $(ls) ,以便理解所谓命令替换是什么意思:
shell 扫描一遍命令行,发现了 $(cmd) 结构,便将 $(cmd) 中的 cmd 执行一次,得到其标准输出,再将此输出放到原来命令 echo $(ls) 中的 $(ls) 位置,即替换了 $(ls), 再执行 echo 命令。
如下:
echo $(ls) 被替换成了 echo a b c
这里要注意的是 $(cmd) 中的命令的错误输出是不会被替换的,替换的只是标准输出:
PHP 代码 :
$ var=$( cat d )      ### 文件d在当前目录不存在
cat :  d :  没有那个文件或目录
$ echo  $var

$        ### 显然var变量的值是空的 

3. 一串的命令执行 () 和 {}
() 和 {} 都是对一串的命令进行执行,但有所区别:
A,() 只是对一串命令重新开一个子 shell 进行执行
B,{} 对一串命令在当前 shell 执行
C,() 和 {} 都是把一串的命令放在括号里面,并且命令之间用 ; 号隔开
D,() 最后一个命令可以不用分号
E,{} 最后一个命令要用分号
F,{} 的第一个命令和左括号之间必须要有一个空格
G,() 里的各命令不必和括号有空格
H,() 和 {} 中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令

我们来看几个例子:
PHP 代码 :
$ var= test
$ (var= notest ; echo  $var )        ### 变量var值为notest,此是在子shell中有效
notest
$ echo  $var         ### 父shell中值仍为test
test
$ { var= notest ; echo  $var ;}      ### 注意左括号和var之间要有一个空格
notest
$ echo  $var                      ### 父shell中的var变量的值变为了notest
notest
$ {  var1 = test1 ; var2 = test2 ;echo  $var1 > a ;echo  $var2 ;}     ### 输出test1被重定向到文件a中,
test2                 ### 而test2输出则仍输出到标准输出中。
$  cat a
test1
$ {  var1 = test1 ; var2 = test2 ;echo  $var1 ;echo  $var2 ;}> a              ### 括号内命令的标准输出全部被重定向到文件a中
$  cat a
test1
test2 

4, 几种特殊的替换结构: ${var:-string},${var:+string},${var:=string},${var:?string}
A,${var:-string} 和 ${var:=string}
若变量 var 为空,则用在命令行中用 string 来替换 ${var:-string} ,否则变量 var 不为空时,则用变量 var 的值来替换 ${var:-string}
如:
PHP 代码 :
$ echo  newvar

$ echo ${ newvar :- a }
a
$ echo  newvar              ### 变量newvar的值仍然是空,但上一命令行中${newvar:-a}被替换成了a

$  newvar = b
$ echo ${ newvar :- a }        ### 变量newvar的值不为空时,此命令行中的${newvar:-b}被替换为$newvar,即b
b


对于 ${var:=string} 的替换规则和 ${var:-string} 是一样的,所不同之处是 ${var:=string} 若 var 为空时,用 string 替换 ${var:=string} 的同时,把 string 赋给变量 var :
PHP 代码 :
$ echo  newvar

$ echo ${ newvar := a }
a
$ echo  newvar            ### 变量newvar被赋值为a,同时${newvar:=a}被替换成a
a
$ echo ${ newvar := b }      ### 变量newvar不为空(其值已被赋为a),则${newvar:=b}被替换为newvar的值(即b)
a
$ echo  $newvar


${var:=string} 很常用的一种用法是,判断某个变量是否赋值,没有的话则给它赋上一个默认值。
如设置默认的编辑器:
PHP 代码 :
echo  You  use  editor : ${ EDITOR :=/ bin / vi } 

B,${var:+string}
${var:+string} 的替换规则和上面的相反,即只有当 var 不是空的时候才替换成 string ,若 var 为空时则不替换或者说是替换成变量 var 的值,即空值。 ( 因为变量 var 此时为空,所以这两种说法是等价的 )
PHP 代码 :
$ echo  $newvar
a
$ echo ${ newvar :+ b }
b
$ echo  $newvar
a
$  newvar =
$ echo ${ newvar :+ b }



C,${var:?string}
替换规则为:若变量 var 不为空,则用变量 var 的值来替换 ${var:?string} ;若变量 var 为空,则把 string 输出到标准错误中,并从脚本中退出。我们可利用此特性来检查是否设置了变量的值。
PHP 代码 :
$  newvar =
$ echo ${ newvar :? 没有设置newvar的值 }
bash :  newvar :  没有设置newvar的值
$  newvar = a
$ echo ${ newvar :? 没有设置newvar的值 }
a


补充扩展:在上面这五种替换结构中 string 不一定是常值的,可用另外一个变量的值或是一种命令的输出。
PHP 代码 :
$ echo ${var:-` date `}
日 3月 6 02 : 10 : 39 CST 2005
$ echo ${var:-$( date )}
日 3月 6 02 : 11 : 46 CST 2005
$  a = test
$ echo ${var:- $a }
test


5.POSIX 标准的扩展计算 :$((exp))
这种计算是符合 C 语言的运算符,也就是说只要符合 C 的运算符都可用在 $((exp)) ,甚至是三目运算符。
注意:这种扩展计算是整数型的计算,不支持浮点型 . 若是逻辑判断,表达式 exp 为真则为 1, 假则为 0 。
PHP 代码 :
$ echo $(( 3 + 2 ))
5
$ echo $(( 3 > 2 ))
1
$ echo $(( 25 < 3  ?  2 : 3 ))
3
$ echo  $var

$ echo $((var= 2 + 3 ))
5
$ echo  $var
5
$ echo $((var++))
5
$ echo  $var
6


好了,上面的例子足够了,这也表明了这种扩展运算是很强大的。

6. 四种模式匹配替换结构: ${var%pattern},${var%%pattern},${var#pattern},${var##pattern}
这四种结构的意义是: ${var%pattern} 和 ${var%%pattern} 表示从最右边 ( 即结尾 ) 匹配的, ${var#pattern} 和 ${var##pattern} 从最左边 ( 即开头 ) 匹配的。其中 ${var%pattern} 和 ${var#pattern} 是最短匹配, ${var%%pattern} 和 ${var##pattern} 是最长匹配。只有在 pattern 中使用了通配符才能有最长最短的匹配,否则没有最长最短匹配之分。

结构中的 pattern 支持通配符, * 表示零个或多个任意字符, ? 表示零个或一个任意字符, [...] 表示匹配中括号里面的字符, [!...] 表示不匹配中括号里面的字符。
PHP 代码 :
$ var= aabbbccbbdbb
$ echo ${var% b }
aabbbccbbdb
$ echo ${var%% b }
aabbbccbbdb
$ echo ${var #a}
abbbccbbdbb
$ echo ${var ##a}
abbbccbbdbb
$ echo ${var%* b }
aabbbccbbdb
$ echo ${var%%* b }

$ echo ${var #a*}
abbbccbbdbb
$ echo ${var ##a*}



上面是简单的例举四种模式匹配替换结构的用法。
32.bash中字符串的处理
1. 得到字符串长度
方法一 :
$echo ${#variable}
code:
PHP 代码 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$ echo ${ #x}
14 

方法二 :
$expr length "$variable"
code:
PHP 代码 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$  expr length  "$x"
14 

方法三 :
$expr "$variable" : ".*"
code:
PHP 代码 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$  expr  "$x"  :  ".*"
14 

2. 查找字符串子串位置
方法 :
$expr index "$variable" "substring"
code:
PHP 代码 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$  expr index  "$x" "is"
3
zhyfly : ~$  expr index  "$x" "t"


(ps: 如果出现重复 , 好象只能查到第一个 , 第二个 , 第三个 ,..., 怎么查到呢 ???)
3. 得到字符串子字符串
方法一 :
$echo ${variable:position:length}
code:
PHP 代码 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$ echo ${ x : 1 : 5 }
his i 

方法二 :
$expr substr "$variable" startposition length
code:
PHP 代码 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$  expr substr  "$x"  1 5
this 

(ps: 注意方法一和方法二中位置的区别 !)
4. 匹配正则表达式之匹配长度
方法 :
$expr match "$x" "string"
code:
PHP 代码 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$  expr match  "$x" "his"
0
zhyfly : ~$  expr match  "$x" "this"
4
zhyfly : ~$  expr match  "$x" "."


5. 字符串的掐头去尾
方法 :
$echo ${variable#startletter*endletter} # # 表示掐头 , 因为键盘上 # 在 $ 前面 , 一个表示最小匹配
$echo ${variable##tartletter*endletter} 两个表示最大匹配
$echo ${variable%startletter*endletter} # % 表示去尾 , 因为键盘上 % 在 $ 后面 , 一个表示最小匹配
$echo ${variable%%startletter*endletter} 两个表示最大匹配
code:
PHP 代码 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$ echo ${ x #t}
his is a test
zhyfly : ~$ echo ${ x #t*h}
is is a test
zhyfly : ~$ echo ${ x #t*s}
  is a test

zhyfly : ~$ echo ${ x ##t*s}
t

zhyfly : ~$ echo ${ x % t }
this is a tes
zhyfly : ~$ echo ${ x % s * t }
this is a te
zhyfly : ~$ echo ${ x % e * t }
this is a t

zhyfly : ~$ echo ${ x %% i * t }
th 

6. 字符 ( 串 ) 的替换
方法 :
$echo ${variable/oldletter/newletter} # 替换一个
$echo ${variable//oldletter/newletter} # 替换所有
code:
PHP 代码 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$ echo ${ x / i / m }
thms is a test
zhyfly : ~$ echo ${ x //i/m}
thms ms a test