生活在 Bash shell 中,熟记以下快捷键,将极大的提高你的命令行操作效率。
编辑命令
- Ctrl + a :移到命令行首
- Ctrl + e :移到命令行尾
- Ctrl + f :按字符前移(右向)
- Ctrl + b :按字符后移(左向)
- Alt + f :按单词前移(右向)
- Alt + b :按单词后移(左向)
- Ctrl + xx:在命令行首和光标之间移动
- Ctrl + u :从光标处删除至命令行首
- Ctrl + k :从光标处删除至命令行尾
- Ctrl + w :从光标处删除至字首
- Alt + d :从光标处删除至字尾
- Ctrl + d :删除光标处的字符
- Ctrl + h :删除光标前的字符
- Ctrl + y :粘贴至光标后
- Alt + c :从光标处更改为首字母大写的单词
- Alt + u :从光标处更改为全部大写的单词
- Alt + l :从光标处更改为全部小写的单词
- Ctrl + t :交换光标处和之前的字符
- Alt + t :交换光标处和之前的单词
- Alt + Backspace:与 Ctrl + w
相同类似,分隔符有些差别 [感谢 rezilla 指正]
重新执行命令
- Ctrl + r:逆向搜索命令历史
- Ctrl + g:从历史搜索模式退出
- Ctrl + p:历史中的上一条命令
- Ctrl + n:历史中的下一条命令
- Alt + .:使用上一条命令的最后一个参数
控制命令
- Ctrl + l:清屏
- Ctrl + o:执行当前命令,并选择上一条命令
- Ctrl + s:阻止屏幕输出
- Ctrl + q:允许屏幕输出
- Ctrl + c:终止命令
- Ctrl + z:挂起命令
Bang (!) 命令
- !!:执行上一条命令
- !blah:执行最近的以 blah 开头的命令,如 !ls
- !blah:p:仅打印输出,而不执行
- !$:上一条命令的最后一个参数,与 Alt + . 相同
- !$:p:打印输出 !$ 的内容
- !*:上一条命令的所有参数
- !*:p:打印输出 !* 的内容
- ^blah:删除上一条命令中的 blah
- ^blah^foo:将上一条命令中的 blah 替换为 foo
- ^blah^foo^:将上一条命令中所有的 blah 都替换为 foo
友情提示:
- 以上介绍的大多数 Bash 快捷键仅当在 emacs 编辑模式时有效,若你将 Bash 配置为 vi 编辑模式,那将遵循 vi 的按键绑定。Bash 默认为 emacs 编辑模式。如果你的 Bash 不在 emacs 编辑模式,可通过
set -o emacs
设置。 - ^S、^Q、^C、^Z 是由终端设备处理的,可用
stty
命令设置。
转自:http://linuxtoy.org/archives/bash-shortcuts.html
之二:
Bash Shell 快捷键
【CTRL 键】
Ctrl + a – Jump to the start of the line
Ctrl + b – Move back a char
Ctrl + c – Terminate the command //用的最多了吧?
Ctrl + d – Delete from under the cursor
Ctrl + e – Jump to the end of the line
Ctrl + f – Move forward a char
Ctrl + k – Delete to EOL
Ctrl + l – Clear the screen //清屏,类似 clear 命令
Ctrl + r – Search the history backwards //查找历史命令
Ctrl + R – Search the history backwards with multi occurrence
Ctrl + u – Delete backward from cursor // 密码输入错误的时候比较有用
Ctrl + xx – Move between EOL and current cursor position
Ctrl + x @ – Show possible hostname completions
Ctrl + z – Suspend/ Stop the command
【补充:】
Ctrl + h – 删除当前字符
Ctrl + w – 删除最后输入的单词
【ALT 键】
平时很少用。有些和远程登陆工具冲突。
Alt + < - Move to the first line in the history
Alt + > – Move to the last line in the history
Alt + ? – Show current completion list
Alt + * – Insert all possible completions
Alt + / – Attempt to complete filename
Alt + . – Yank last argument to previous command
Alt + b – Move backward
Alt + c – Capitalize the word
Alt + d – Delete word
Alt + f – Move forward
Alt + l – Make word lowercase
Alt + n – Search the history forwards non-incremental
Alt + p – Search the history backwards non-incremental
Alt + r – Recall command
Alt + t – Move words around
Alt + u – Make word uppercase
Alt + back-space – Delete backward from cursor
// SecureCRT 如果没有配置好,这个就很管用了。
【其他特定的键绑定:】
输入 bind -P 可以查看所有的键盘绑定。这一系列我觉得更为实用。
Here “2T” means Press TAB twice
$ 2T – All available commands(common) //命令行补全,我认为是 Bash 最好用的一点
$ (string)2T – All available commands starting with (string)
$ /2T – Entire directory structure including Hidden one
$ ./2T – Only Sub Dirs inside including Hidden one
$ *2T – Only Sub Dirs inside without Hidden one
$ ~2T – All Present Users on system from “/etc/passwd” //第一次见到,很好用
$ $2T – All Sys variables //写Shell脚本的时候很实用
$ @2T – Entries from “/etc/hosts” //第一次见到
$ =2T – Output like ls or dir //好像还不如 ls 快捷
Esc + T – 交换光标前面的两个单词
【命令行历史】
history 显示命令历史列表
↑(Ctrl p) 显示上一条命令
↓(Ctrl n) 显示下一条命令
!num 执行命令历史列表的第num条命令
!! 执行上一条命令
!?string? 执行含有string字符串的最新命令
Ctrl + r - 然后输入若干字符,开始向上搜索包含该字符的命令,继续按Ctrl r,搜索上一条匹配的命令
Ctrl + s - 与Ctrl + 类似,只是正向检索
Alt + < - 历史列表第一项
Alt + > - 历史列表最后一项
ls !$ 执行命令ls,并以上一条命令的参数为其参数
【命令行编辑】
Ctrl + u - 剪切命令行中光标所在处之前的所有字符(不包括自身)
Ctrl + k - 剪切命令行中光标所在处之后的所有字符(包括自身)
Ctrl + a - 移动到当前行的开头
Ctrl + e - 移动到当前行的结尾
Ctrl + d - 删除光标所在处字符
Ctrl + h - 删除光标所在处前一个字符
Ctrl + y - 粘贴刚才所删除的字符
Ctrl + c - 删除整行
Ctrl + (x u) - 按住Ctrl的同时再先后按x和u,撤销刚才的操作
Ctrl + w - 剪切光标所在处之前的一个词(以空格、标点等为分隔符)
Alt + d - 剪切光标之后的词
Ctrl + f - 光标向前移动一个字符,相当与->
Ctrl + b - 光标向后移动一个字符,相当与<-
Alt + f - 光标向前移动一个单词
Alt + b - 光标向后移动一个单词
Esc + f - 移动到当前单词的结尾
Esc + b - 移动到当前单词的开头
Ctrl + t - 颠倒光标所在处及其之前的字符位置,并将光标移动到下一个字符
Alt + t - 交换当前与以前单词的位置
Esc + t - 颠倒光标所在处及其相邻单词的位置
Alt + u - 把当前词转化为大写
Alt + l - 把当前词转化为小写
Alt + c - 把当前词汇变成首字符大写
Ctrl + v - 插入非凡字符,如Ctrl v Tab加入Tab字符键
alt + . — 插入最有输入的命令。
alt + b — 光标移动到前一个单词处。
Esc + w - 删除光标所在处之前的字符至其单词尾(以空格、标点等为分隔符)
【控制】
Ctrl + l - 清屏
ctrl + c — 终止当前命令或进程。
ctrl + d — 终止shell。
ctrl + z — 将进程放入后台,可以用fg命令将放入后台的命令调入前台。
Ctrl + s - 挂起当前shell
Ctrl + q - 重新启用挂起的shell
shell(bash)命令行快捷方式
转自:老蒋记事本
posted @ 2011-12-31 01:44 天晴如许 阅读(15) 评论(0) 编辑
Linux Shell History (快速使用Linux命令)
使用history命令可以调出历史曾经用过的命令列表
shell> history
994 cat config.nice
995 cd /usr/local/src
996 ls
997 cd /usr/src
998 ls
999 dmesg
1000 history
1001 history 100
如果你想重新执行"cd /usr/local/src" 那就可以直接这样调出历史:
shell> !995
对简短容易的命令来说,可能没什么用处,但是对于
cd /usr/local/src/ZendOptimizer-3.0.0-linux-glibc21-i386
./configure --prefix=/usr/local/gd --without-x --without-freetype --without-fontconfig --without-png
这样的长命令,可能就有点帮助了,
获取上个命令中的某个参数.
比如你执行了如下的操作
shell> ls /bin/sh
shell> file /bin/sh
比较一下,两个命令的参数是一样的,这时候,你就可以使用"!"来获得上一个命令的参数了.如下:
shell> ls /bin/sh
shell> file !:$
"!"会提示shell获得上面的命令的某部分,作为当前的输入,比如$表示结尾,那就是获得了ls命令的最后一个参数(其实这里也是第一个参数.
再来看一个长点的。
shell> tar zxvf httpd-2.0.59.tar.bz2
这显然是一个错误的输入,大家都知道bz2是使用bzip解压缩的,对应的tar参数,应当是使用"jxvf". 那我们可以立即这样修正它:
shell> tar jxvf !:2
"!:2"会获得上面tar命令的第2个参数,作为当前的输入. 获取的历史输入,并不只是可以单独使用,也可以作为命令的一部分象这样:
shell> tar zxvf httpd-2.0.59.tar.bz2
shell> tar jxvf !:2 -C /usr/tmo
执行完上面的获取,命令被替换成了tar jxvf httpd-2.0.59.tar.bz2 -C /usr/tmo
那就会按照-C指定的路径把包解压缩到/usr/tmo中.
命令执行后的结果:
tar: /usr/tmo: Cannot chdir: No such file or directory
tar: Error is not recoverable: exiting now
sorry,我一不小心又敲错了.我本来是想解压缩到/usr/tmp中的这时候另一个更有趣的命令派上用场了,
"^"号(替换)
shell> ^mo^mp
这会把上一个命令行里的mo替换成mp
神奇吧,你的指法再快,只是在浪费时间,我轻敲6个字符,就搞定了上面的错误.
一些有用的历史命令
!是bash和cshell默认的历史替换符号
!! 重复最后一个命令
!:s/xy/yx 这个命令会把最后一个命令里的xy替换成yx
比如etho xy !:s/xy:/yx
!so 重复最近以so开始的命令
!?fn? 重复最近喊有fn的命令,在某个参数中或某个命令的名称中都可以使用
!32 执行号码为32的命令
!! & 会在最后一个命令的末尾加上& (可以加上任意内容)
!:0 挑选出命令的名称,而不是整行
!:3 第参数
!:2-4 第2到4个参数
!:-3 从第0个到第三个参数
!^ 第一个参数
!$ 最后一个参数
!* 第一个到最后一个参数
!:2* 第2个到最后一个
!:2- 从第2个开始,但不要结尾参数
!?fn?% 给出第一个包含 fn的次(sort fn1 fn2 fn3 ... =>echo !?fn?% =>echo fn1)
更cool的,请参
man 3 history
和其他的一些man page
命令行编程 shell是直接支持命令行编程的. 比如:
sh > /usr/local/src
sh > ls *z
--------------------------------------------------------------------------------
ZendOptimizer-3.0.0-linux-glibc21-i386.tar.gz mod_fastcgi-2.4.2.tar.gz
dia-0.94.tar.gz mod_fcgid.1.10.tar.gz
gd-2.0.33.tar.gz mysql-4.0.27.tar.gz
jpegsrc.v6b.tar.gz mysql-standard-4.0.26-pc-linux-gnu-i686-glibc23.tar.gz
lighttpd-1.4.11.tar.gz
--------------------------------------------------------------------------------
开工了,我要把这些东西装起来,解压缩吧,好多呀,要敲n个命令.
别急,这不会花费你几秒钟的时间;
sh > for i in `ls *z`
sh > do
sh > tar zxvf $i
sh > done
眼晕了吧,不一会所有的包都解压缩了。
这只是一个简单的应用,其实你还可以加上判断,把gz和bz2,rar什么的分别用不同的程序解压缩.
使用sed和shell配合,你甚至可以一次修改一大堆的虚拟主机配置文件中的主目录:
sh > for i in `ls`
sh > do
sh > sed -i 's/\/home\//\/disk1\\/home\//g\' $i
sh > done
大搬家!把所有用户的虚拟主机都从/home搬迁到/disk1/home中了.
转自:http://blog.chinaunix.net/u/76/showart_155742.html
posted @ 2011-12-31 01:05 天晴如许 阅读(81) 评论(0) 编辑
2011年12月30日 #
shell输出格式化
echo -e "one;two;thr ee ;f\t our\t " | awk -F';' '{gsub(" ","",$3);gsub(/^[ \t]+/,"",$4);print $3,$4}'
awk中使用gsub函数将字段中的空格去除,支持正则。
[admin@inc-dw-151-5 xuyuqin]$ du -sh ~/yunti_compare/hadoop_20111213/EnLog/10/*dat | awk -F '/home/admin/yunti_compare/hadoop_20111213/EnLog/10/' '{gsub(/[ \t]+/,"",$1); printf("%-20s %s\n",$1,$2)}' | sort -nr -k1
386M listcookie_fatdt0.dat
……
264M path_fatdt1.dat
76M referpage_fatdt0.dat
48M referpage_fatdt1.dat
……
……
上面命令在awk中使用printf对输出内容进行格式化。
posted @ 2011-12-30 20:17 天晴如许 阅读(98) 评论(0) 编辑
eclipse CDT MinGW GNU C++ cout在控制台无输出
在eclipse下,用CDT,MinGW GNU C++,发现cout在console中没有输出
网上说是32位和64位的问题,我机器上全是32位的。折腾了半天,重新创建project,如下选择解决问题:
创建Project时,不要选择“Empty Project”,选择“Hello World C++ Project”
posted @ 2011-12-30 19:42 天晴如许 阅读(113) 评论(0) 编辑
shell调用sqlplus查询oracle
[oracle@hb shell_test]$ cat echo_time
#!/bin/sh
一.最简单的调用sqlplus
sqlplus -S "sys/unimas as sysdba" << !
select to_char(sysdate,'yyyy-mm-dd') today from dual;
exit;
!
[oracle@hb shell_test]$ ./echo_time
TODAY
----------
2011-03-21
-S 是silent mode,不输出类似“SQL>”,连接数据库,关闭数据库之类的信息。
eof可以是任何字符串 比如"laldf"那么当你输入单独一行laldf时"shell认为输入结束,但是必须表示块开始必须使用<<;
开始和结束要匹配这个符号“<<”后面的内容
举例子:
[oracle@hb shell_test]$ sqlplus -s "sys/unimas as sysdba" << abc
> select to_char(sysdate,'yyyy-mm-dd') today from dual;
> exit;
> abc
TODAY
----------
2011-03-21
二.sqlplus的结果传递给shell的方法一
[oracle@hb shell_test]$ cat test2.sh
#!/bin/bash
VALUE=`sqlplus -S "test/unimas" << !
set heading off
set feedback off
set pagesize 0
set verify off
set echo off
select to_char(sysdate,'yyyy-mm-dd') today from dual;
exit
!`
echo $VALUE
if [ -n "$VALUE" ]; then
echo "The rows is $VALUE"
exit 0
else
echo "There is no row"
fi
三.sqlplus的结果传递给shell的方法二
[oracle@hb shell_test]$ cat test1.sh
#!/bin/bash
sqlplus -S "test/unimas" << !
set heading off
set feedback off
set pagesize 0
set verify off
set echo off
col coun new_value v_coun
select count(*) coun from lesson;
exit v_coun
!
VALUE="$?"
echo "show row:$VALUE"
col coun new_value v_coun v_coun为number类型。因为exit 只能返回数值类型。
四.把shell参数传递给sqlplus
#!/bin/bash
t_id="$1"
sqlplus -S "test/unimas" << !
set heading off
set feedback off
set pagesize 0
set verify off
set echo off
select teachername from teacher where id=$t_id;
exit
!
五.sqlplus的结果存储在文件中
#!/bin/sh
sqlplus -S "test/unimas"<<EOF
set heading off
set feedback off
set pagesize 0
set verify off
set echo off
spool spool_file
SELECT * from teacher;
spool off
exit;
EOF
http://blog.chinaunix.net/space.php?uid=9124312&do=blog&id=181372
####################################################################################################################################
查看调度系统状态脚本:
#!/bin/sh
if [[ -z "$1" ]] || [[ "$1" -ne 0 && "$1" -ne 2 ]] #使用[[ ]] 进行逻辑短路操作
then
echo "Please input your parameter: query status[0,2]!"
exit
fi
#for buname in cnlog enlog ItLog JrLog AuLog InnerLog
for buname in cnlog enlog
do
sqlplus -S 'etl/etl@dw_testdb' << abc #使用 << EOF方式输入信息
set line 155
set pages 9999
SELECT /*+ PARALLEL(a,4) */ * FROM $buname.hla_job_rec a where status = $1;
exit
abc
done
posted @ 2011-12-30 19:41 天晴如许 阅读(210) 评论(0) 编辑
Linux下脚本实现交互输入
需要处理的问题是:
1、scp远程拷贝每个源文件均需要输入密码。源文件是通过正则匹配的,scp支持,但每个文件或目录需要手工输入远程机器的密码,文件大的时候总不能守着吧
可选的解决方案是:打通ssh通道。但我只需要处理一次,原则上生产环境是不打通到开发环境的ssh通道的。事前事后都得联系SA处理,麻烦
2、scp远程拷贝目标目录只能指定一个已存在的目录,不支持动态生成。
比如:scp -r ./*/*c*/*2* admin@10.20.151.5:/home/admin/yunti_compare,这是可以的,只是每次需要手动输入密码,如果我想将目标文件 放到:/home/admin/yunti_compare/*,其中*对应源目录的名字呢?搞不定。
最后,使用expect脚本实现交互。如下所示。
如果问题规模更复杂些,特别是文件备份,建议使用:rsync
#!/usr/bin/expect
set orgpath [lindex $argv 0 ]
set target [lindex $argv 1 ]
spawn ssh admin@10.20.151.5
expect ".*password:"
send "log2011\n"
expect "].*"
send "mkdir -p $target\n"
expect "].*"
send "exit\n"
#interact
spawn scp -r $orgpath admin@10.20.151.5:$target
expect ".*password:"
send "log2011\n"
expect eof
exit
#scp hadoop1的按小时分析的结果文件,采样获取10点和22点文件到开发环境151.5
for buname in `du -sh /data/work/*/SqlldrDat/20111213/10 | awk -F '/' '{print $4}'`
do
#scp -r /data/work/*/SqlldrDat/20111213/10 admin@10.20.151.5:/home/admin/yunti_compare/hadoop_20111213/*/10
#scp -r /data/work/*/SqlldrDat/20111213/22 admin@10.20.151.5:/home/admin/yunti_compare/hadoop_20111213/*/22
./copy_log.expect "/data/work/$buname/SqlldrDat/20111213/10" "/home/admin/yunti_compare/hadoop_20111213/$buname"
./copy_log.expect "/data/work/$buname/SqlldrDat/20111213/22" "/home/admin/yunti_compare/hadoop_20111213/$buname"
done
#scp hadoop1的按天分析文件到开发环境151.5
for buname in AeCtr AuLog CnP4PClick EnP4P EnP4PClick EnWeb InnerClickstat InnerCtr InnerLog MytLog
do
target_dir="/home/admin/yunti_compare/hadoop_20111213/$buname""_day"
./copy_log.expect "/data/work/$buname/SqlldrDat/20111213" $target_dir
done
################################################### Linux下脚本实现交互输入举例结束 #####################################################
posted @ 2011-12-30 17:51 天晴如许 阅读(7) 评论(0) 编辑
2011年12月9日 #
C++可执行文件相关信息查找
1、查看可执行文件的相关动态链接库:ldd
[admin@logforward EN]$ ldd genIpData
libGeoIP.so.1 => /home/admin/Geoip/lib/libGeoIP.so.1 (0x00002b34c9a4c000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x000000301a400000)
libm.so.6 => /lib64/libm.so.6 (0x0000003008200000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003019000000)
libc.so.6 => /lib64/libc.so.6 (0x0000003007a00000)
/lib64/ld-linux-x86-64.so.2 (0x0000003007600000)
2、查看可执行文件是多少位的:file
[admin@logforward EN]$ file genIpData
genIpData: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
3、查看可执行文件的符号:nm
[admin@logforward EN]$ nm genIpData
U GeoIPRecord_delete
U GeoIP_open_type
U GeoIP_record_by_addr
0000000000602af0 d _DYNAMIC
0000000000602cc8 d _GLOBAL_OFFSET_TABLE_
0000000000400d16 t _GLOBAL__I_main
0000000000401fe8 R _IO_stdin_used
w _Jv_RegisterClasses
U _Unwind_Resume@@GCC_3.0
……
GNU Binutils
gnu binutils安装指导参见: 安装 Binutils-2.14 在 第 6 章.
官方下载地址
Binutils (2.14):
ftp://ftp.gnu.org/gnu/binutils/
Binutils的内容
Binutils 是一组开发工具,包括连接器,汇编器和其他用于目标文件和档案的工具。
安装下列程序: addr2line, ar, as, c++filt, gprof, ld,nm, objcopy, objdump, ranlib, readelf, size, strings 和 strip
安装下列库文件: libiberty.a, libbfd.[a,so] 和libopcodes.[a,so]
简短说明
addr2line 把程序地址转换为文件名和行号。在命令行中给它一个地址和一个可执行文件名,它就会使用这个可执行文件的调试信息指出在给出的地址上是哪个文件以及行号。
ar 建立、修改、提取归档文件。归档文件是包含多个文件内容的一个大文件,其结构保证了可以恢复原始文件内容。
as 主要用来编译GNU C编译器gcc输出的汇编文件,产生的目标文件由连接器ld连接。
c++filt 连接器使用它来过滤 C++ 和 Java 符号,防止重载函数冲突。
gprof 显示程序调用段的各种数据。
ld 是连接器,它把一些目标和归档文件结合在一起,重定位数据,并链接符号引用。通常,建立一个新编译程序的最后一步就是调用ld。
nm 列出目标文件中的符号。
objcopy把一种目标文件中的内容复制到另一种类型的目标文件中.
objdump 显示一个或者更多目标文件的信息。显示一个或者更多目标文件的信息。使用选项来控制其显示的信息。它所显示的信息通常只有编写编译工具的人才感兴趣。
ranlib 产生归档文件索引,并将其保存到这个归档文件中。在索引中列出了归档文件各成员所定义的可重分配目标文件。
readelf 显示ebf格式可执行文件的信息。
size 列出目标文件每一段的大小以及总体的大小。默认情况下,对于每个目标文件或者一个归档文件中的每个模块只产生一行输出。
strings 打印某个文件的可打印字符串,这些字符串最少4个字符长,也可以使用选项-n设置字符串的最小长度。默认情况下,它只打印目标文件初始化和可加载段中的可打印字符;对于其它类型的文件它打印整个文件的可打印字符,这个程序对于了解非文本文件的内容很有帮助。
strip 丢弃目标文件中的全部或者特定符号。
libiberty 包含许多GNU程序都会用到的函数,这些程序有: getopt, obstack, strerror, strtol 和 strtoul.
libbfd 二进制文件描述库.
libopcodes 用来处理opcodes的库, 在生成一些应用程序的时候也会用到它, 比如objdump.Opcodes是文本格式可读的处理器操作指令.
Binutils 安装依赖关系
Binutils 依赖于: Bash, Coreutils, Diffutils, GCC, Gettext,Glibc, Grep, Make, Perl, Sed, Texinfo.
posted @ 2011-12-09 13:49 天晴如许 阅读(10) 评论(0) 编辑
shell中容易混淆的各种括号语法辨析
几种shell里的小括号,大括号结构和有括号的变量,命令的用法
linux bash shell中,单引号、 双引号,反引号(``)的区别及各种括号的区别
posted @ 2011-12-09 06:18 天晴如许 阅读(9) 评论(0) 编辑
shell中if条件字符串、数字比对,[[ ]]和[ ]区别
引用:
http://www.51testing.com/?uid-7701-action-viewspace-itemid-13731
http://blog.csdn.net/sunboy_2050/article/details/6836382
学习shell的时候总是被shell里的条件判断方式搞得头疼,经常不知道改 用[],[[]],(())还是test,let,而很少有书把它们的关系讲解的很清楚(应该是我悟性差或是看书太少),今天总结一下,基础的东西如它们 的使用方法不再赘述,重点说说它们的区别的使用时应该注意的地方。
先说[]和test,两者是一样的,在命令行里test expr和[ expr ]的效果相同。test的三个基本作用是判断文件、判断字符串、判断整数。支持使用与或非将表达式连接起来。要注意的有:
1.test中可用的比较运算符只有==和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq, -gt这种形式。无论是字符串比较还是整数比较都千万不要使用大于号小于号。当然,如果你实在想用也是可以的,对于字符串比较可以使用尖括号的转义形式, 如果比较"ab"和"bc":[ ab \< bc ],结果为真,也就是返回状态为0.
然后是[[ ]],这是内置在shell中的一个命令,它就比刚才说的test强大的多了。支持字符串的模式匹配(使用=~操作符时甚至支持shell的正则表达 式)。简直强大的令人发指!逻辑组合可以不使用test的-a,-o而使用&&,||这样更亲切的形式(针对c、Java程序员)。当 然,也不用想的太复杂,基本只要记住
1.字符串比较时可以把右边的作为一个模式(这是右边的字符串不加双引号的情况下。如果右边的字符串加了双引号,则认为是一个文本字符串。),而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。
另外要注意的是,使用[]和[[]]的时候不要吝啬空格,每一项两边都要有空格,[[ 1 == 2 ]]的结果为“假”,但[[ 1==2 ]]的结果为“真”!后一种显然是错的
3.最后就是let和(()),两者也是一样的(或者说基本上是一样的,双括号比let稍弱一些)。主要进行算术运算(上面的两个都不行),也比较适合进 行整数比较,可以直接使用熟悉的<,>等比较运算符。可以直接使用变量名如var而不需要$var这样的形式。支持分号隔开的多个表达式
####################################################################################################################################
1. 首先,尽管很相似,但是从概念上讲,二者是不同层次的东西。
"[[",是关键字,许多shell(如ash bsh)并不支持这种方式。ksh, bash(据说从2.02起引入对[[的支持)等支持。
"["是一条命令, 与test等价,大多数shell都支持。在现代的大多数sh实现中,"["与"test"是内部(builtin)命令,换句话说执行"test"/"["时不会调用/some/path/to/test这样的外部命令(如果有这样的命令的话)。
2.[[]]结构比Bash版本的[]更通用。在[[和]]之间的所有的字符都不会被文件扩展或是标记分割,但是会有参数引用和命令替换。
用[[ ... ]]测试结构比用[ ... ]更能防止脚本里的许多逻辑错误。比如说,&&,||,<和>操作符能在一个[[]]测试里通过,但在[]结构会发生错误。
3.(( ))结构扩展并计算一个算术表达式的值。如果表达式值为0,会返回1或假作为退出状态码。一个非零值的表达式返回一个0或真作为退出状态码。这个结构和先前test命令及[]结构的讨论刚好相反。
4.[ ... ]为shell命令,所以在其中的表达式应是它的命令行参数,所以串比较操作符">" 与"<"必须转义,否则就变成IO改向操作符了(请参看上面2中的例子)。在[[中"<"与">"不需转义;
由于"[["是关键字,不会做命令行扩展,因而相对的语法就稍严格些。例如
在[ ... ]中可以用引号括起操作符,因为在做命令行扩展时会去掉这些引号,而在[[ ... ]]则不允许这样做。
5.[[ ... ]]进行算术扩展,而[ ... ]不做
6.[[ ... && ... && ... ]] 和 [ ... -a ... -a ...] 不一样,[[ ]] 是逻辑短路操作,而 [ ] 不会进行逻辑短路
1)在ksh中的test
数字的运算可使用let、(( )) ,其中运算时不需要变量$符号,运算符为 +、-、*、/、% ,不建议使用expr
数字的比较使用 (( )) ,其运算符 >、>=、<、<=、==、!=
可以使用算术扩展,如:(( 99+1 <= 101 ))
字符表达式的比较使用 [[ ]] ,其运算符 =、!=、-n、-z
文件表达式的测试使用 [[ ]] ,其运算符 -r、-l、-w、-x、-f、-d、-s、-nt、-ot
逻辑表达式的测试使用 [[ ]] ,其运算符 !、&&、||
数字比较、字符比较、逻辑测试可以组合,如$ [[ "a" != "b" && 4 -gt 3 ]]
支持bash中的通配符扩展,如:[[ hest = h??t ]] 、[ hest = h*t ]]
使用 (( )) 时,不需要空格分隔各值和运算符,使用 [[ ]] 时需要用空格分隔各值和运算符。
2)bash与ksh中的 [[ ]] 不同
在redhat9的bash中也可以使用 [[ ]] 符号。但是建议严格按照上面的原则使用。
在bash中,数字的比较最好使用 (( )),虽说可以使用 [[ ]],但若在其内使用运算符 >、>=、<、<=、==、!= 时,其结果经常是错误的,不过若在 [[ ]] 中使用 [ ] 中的运算符“-eq、-ne、-le、-lt、-gt、-ge”等,还尚未发现有错。因此诸如$ [[ " a" != “b” && 4 > 3 ]] 这类组合(见上)也不可以在bash中使用,其出错率很高。
例:[[ "a" != "b" && 10 > 2 ]] 判断结果就不正常。
诸如 [ 2 \< 10 ]、[[ 2 < 10 ]] 都是不要使用。使用算术扩展最好用 (( 99+1 == 100 )) ,而不要使用[[ 99+1 -eq 100 ]] 。
####################################################################################################################################
运算符 | 描述 | 示例 |
文件比较运算符 | ||
-e filename | 如果 filename 存在,则为真 | [ -e /var/log/syslog ] |
-d filename | 如果 filename 为目录,则为真 | [ -d /tmp/mydir ] |
-f filename | 如果 filename 为常规文件,则为真 | [ -f /usr/bin/grep ] |
-L filename | 如果 filename 为符号链接,则为真 | [ -L /usr/bin/grep ] |
-r filename | 如果 filename 可读,则为真 | [ -r /var/log/syslog ] |
-w filename | 如果 filename 可写,则为真 | [ -w /var/mytmp.txt ] |
-x filename | 如果 filename 可执行,则为真 | [ -L /usr/bin/grep ] |
filename1 -nt filename2 | 如果 filename1 比 filename2 新,则为真 | [ /tmp/install/etc/services -nt /etc/services ] |
filename1 -ot filename2 | 如果 filename1 比 filename2 旧,则为真 | [ /boot/bzImage -ot arch/i386/boot/bzImage ] |
字符串比较运算符 (请注意引号的使用,这是防止空格扰乱代码的好方法) | ||
-z string | 如果 string 长度为零,则为真 | [ -z "$myvar" ] |
-n string | 如果 string 长度非零,则为真 | [ -n "$myvar" ] |
string1 = string2 | 如果 string1 与 string2 相同,则为真 | [ "$myvar" = "one two three" ] |
string1 != string2 | 如果 string1 与 string2 不同,则为真 | [ "$myvar" != "one two three" ] |
算术比较运算符 | ||
num1 -eq num2 | 等于 | [ 3 -eq $mynum ] |
num1 -ne num2 | 不等于 | [ 3 -ne $mynum ] |
num1 -lt num2 | 小于 | [ 3 -lt $mynum ] |
num1 -le num2 | 小于或等于 | [ 3 -le $mynum ] |
num1 -gt num2 | 大于 | [ 3 -gt $mynum ] |
num1 -ge num2 | 大于或等于 | [ 3 -ge $mynum ] |
测试命令 test命令用于检查某个条件是否成立,它可以进行数值、字符和文件3个方面的测试,其测试符和相应的功能分别如下。 (1)数值测试: -eq 等于则为真。 -ne 不等于则为真。 -gt 大于则为真。 -ge 大于等于则为真。 -lt 小于则为真。 -le 小于等于则为真。 (2)字串测试: = 等于则为真。 != 不相等则为真。 -z字串 字串长度伪则为真。 -n字串 字串长度不伪则为真。 (3)文件测试: -e文件名 如果文件存在则为真。 -r文件名 如果文件存在且可读则为真。 -w文件名 如果文件存在且可写则为真。 -x文件名 如果文件存在且可执行则为真。 -s文件名 如果文件存在且至少有一个字符则为真。 -d文件名 如果文件存在且为目录则为真。 -f文件名 如果文件存在且为普通文件则为真。 -c文件名 如果文件存在且为字符型特殊文件则为真。 -b文件名 如果文件存在且为块特殊文件则为真 |
条件变量替换:
Bash Shell可以进行变量的条件替换,既只有某种条件发生时才进行替换,替换
条件放在{}中.
(1) ${value:-word}
当变量未定义或者值为空时,返回值为word的内容,否则返回变量的值.
(2) ${value:=word}
与前者类似,只是若变量未定义或者值为空时,在返回word的值的同时将word赋值给value
(3) ${value:?message}
若变量以赋值的话,正常替换.否则将消息message送到标准错误输出(若此替换出现在Shell程序中,那么该程序将终止运行)
(4) ${value:+word}若变量以赋值的话,其值才用word替换,否则不进行任何替换
(5) ${value:offset}${value:offset:length}
从变量中提取子串,这里offset和length可以是算术表达式.
(6) ${#value}
变量的字符个数
(7) ${value#pattern}${value##pattern}
去掉value中与pattern相匹配的部分,条件是value的开头与pattern相匹配
#与##的区别在于一个是最短匹配模式,一个是最长匹配模式.
(8) ${value%pattern}
${value%%pattern}于(7)类似,只是是从value的尾部于pattern相匹配,%与%%的区别与#与##一样
(9) ${value/pattern/string}
${value//pattern/string}进行变量内容的替换,把与pattern匹配的部分替换为string的内容,/与//的区别与上同
注意: 上述条件变量替换中,除(2)外,其余均不影响变量本身的值
#!/bin/bash
var1="1"
var2="2"
下面是并且的运算符-a,另外注意,用一个test命令就可以了,还有if条件后面的分号
if test $var1 = "1"-a $var2 = "2" ; then
echo "equal"
fi
下面是或运算符 -o,有一个为真就可以
if test $var1 != "1" -o $var2 != "3" ; then
echo "not equal"
fi
下面是非运算符 !
if条件是为真的时候执行,如果使用!运算符,那么原表达式必须为false
if ! test $var1 != "1"; then
echo "not 1"
fi
以上三个if都为真,所以三个echo都会打印
在一个文档把这几个运算法说的一塌糊涂,于是自己动手实验了一下
------------------------------------------------------------------------------------------------------
二元比较操作符,比较变量或者比较数字.注意数字与字符串的区别.
整数比较
-eq 等于,如:if [ "$a" -eq "$b" ]
-ne 不等于,如:if [ "$a" -ne "$b" ]
-gt 大于,如:if [ "$a" -gt "$b" ]
-ge 大于等于,如:if [ "$a" -ge "$b" ]
-lt 小于,如:if [ "$a" -lt "$b" ]
-le 小于等于,如:if [ "$a" -le "$b" ]
< 小于(需要双括号),如:(("$a" < "$b"))
<= 小于等于(需要双括号),如:(("$a" <= "$b"))
> 大于(需要双括号),如:(("$a" > "$b"))
>= 大于等于(需要双括号),如:(("$a" >= "$b"))
字符串比较
= 等于,如:if [ "$a" = "$b" ]
== 等于,如:if [ "$a" == "$b" ],与=等价
注意:==的功能在[[]]和[]中的行为是不同的,如下:
1 [[ $a == z* ]] # 如果$a以"z"开头(模式匹配)那么将为true
2 [[ $a == "z*" ]] # 如果$a等于z*(字符匹配),那么结果为true
3
4 [ $a == z* ] # File globbing 和word splitting将会发生
5 [ "$a" == "z*" ] # 如果$a等于z*(字符匹配),那么结果为true
一点解释,关于File globbing是一种关于文件的速记法,比如"*.c"就是,再如~也是.
但是file globbing并不是严格的正则表达式,虽然绝大多数情况下结构比较像.
!= 不等于,如:if [ "$a" != "$b" ]
这个操作符将在[[]]结构中使用模式匹配.
< 小于,在ASCII字母顺序下.如:
if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ]
注意:在[]结构中"<"需要被转义.
> 大于,在ASCII字母顺序下.如:
if [[ "$a" > "$b" ]]
if [ "$a" \> "$b" ]
注意:在[]结构中">"需要被转义.
具体参考Example 26-11来查看这个操作符应用的例子.
-z 字符串为"null".就是长度为0.
-n 字符串不为"null"
注意:
使用-n在[]结构中测试必须要用""把变量引起来.使用一个未被""的字符串来使用! -z
或者就是未用""引用的字符串本身,放到[]结构中。虽然一般情况下可
以工作,但这是不安全的.习惯于使用""来测试字符串是一种好习惯.
posted @ 2011-12-09 05:42 天晴如许 阅读(11) 评论(0) 编辑
shell中awk多变量赋值
场景描述:shell脚本中有下面三个赋值语句:
a=`echo "1.0.0.0 1.0.0.255 海外 海外" | awk '{print $1}'`
b=`echo "1.0.0.0 1.0.0.255 海外 海外" | awk '{print $2}'`
c=`echo "1.0.0.0 1.0.0.255 海外 海外" | awk '{print $3}'`
echo a=$a b=$b c=$c
怎样用一句话可以给a、b、c赋值呢?
方法:
echo "1.0.0.0 1.0.0.255 海外 海外" | awk '{print $1,$2,$3}' | while read a b c
do
echo a=$a b=$b c=$c
done
最终脚本中实现:
while read a b c d
do
echo a=$a b=$b c=$c
done < ./IP.data
这是因为IP.data每行只有四个字段,需要前三个,那么可以这么使用。其实依然是用while read的方法
在linux命令行模式下,可以这么实现:
read a b c < <(echo "1.0.0.0 1.0.0.255 海外 海外" | awk '{print $1,$2,$3}')
echo a=$a b=$b c=$c
疑问:
1、如果将上面的语句放在shell脚本中,执行报错:
[admin@inc-dw-151-5 backup]$ cat a.sh
#!/bin/sh
read a b c < <(echo "1.0.0.0 1.0.0.255 海外 海外" | awk '{print $1,$2,$3}')
[admin@inc-dw-151-5 backup]$ chmod +x a.sh; ./a.sh; rm ./a.sh
./a.sh: line 2: syntax error near unexpected token `<'
./a.sh: line 2: `read a b c < <(echo "1.0.0.0 1.0.0.255 海外 海外" | awk '{print $1,$2,$3}')'
2、如果将语句在linux下稍作修改,执行报错:
[admin@inc-dw-151-5 backup]$ read a b c < (echo "1.0.0.0 1.0.0.255 海外 海外" | awk '{print $1,$2,$3}')
-bash: syntax error near unexpected token `('
[admin@inc-dw-151-5 backup]$ read a b c < < (echo "1.0.0.0 1.0.0.255 海外 海外" | awk '{print $1,$2,$3}')
-bash: syntax error near unexpected token `<'
[admin@inc-dw-151-5 backup]$ read a b c < m<(echo "1.0.0.0 1.0.0.255 海外 海外" | awk '{print $1,$2,$3}')
-bash: m/dev/fd/62: 没有那个文件或目录
想先把数据放到m这个文件里面,结果被直接定向到了m/dev/fd/62,那么 < <应该是使用了特殊的文件描述符,但还没找到说明文档
posted @ 2011-12-09 00:59 天晴如许 阅读(127) 评论(0) 编辑