#! /bin/sh newone="mpich" #这里添加的用户为mpich,你也可以改动。 hostloc="/etc/hosts" # create a new member and input the password useradd -m $newone passwd $newone# get the admin member who | awk '{print $1}' >> tmpuser user=`head -n 1 tmpuser` # get the admin member's groups and remove the self group groupinfo=`groups $user | awk '{print}'| sed 's/'$user'//'` # copy the groups to the new member for i in $groupinfo;do gpasswd -a $newone $i done echo `groups $newone`
Posted onEdited onWord count in article: 14kReading time ≈13 mins.
转自:http://ss64.com/bash/
好不容易才找到…
[alias](http://ss64.com/bash/alias.html)
Create an alias
apropos Search Help manual pages (man -k)
[apt-get](http://www.debian.org/doc/manuals/apt-howto/ch-apt-get.en.html)
Search for and install software packages (Debian)
[aspell](http://aspell.net/)
Spell Checker
[awk](http://ss64.com/bash/awk.html)
Find and Replace text, database sort/validate/index
b
bash GNU Bourne-Again SHell
[bc](http://ss64.com/bash/bc.html)
Arbitrary precision calculator language
[bg](http://ss64.com/bash/bg.html)
Send to background
[break](http://ss64.com/bash/break.html)
Exit from a loop
[builtin](http://ss64.com/bash/builtin.html)
Run a shell builtin
[bzip2](http://www.bzip.org/)
Compress or decompress named file(s)
c
[cal](http://ss64.com/bash/cal.html)
Display a calendar
[case](http://ss64.com/bash/case.html)
Conditionally perform a command
[cat](http://ss64.com/bash/cat.html)
Display the contents of a file
[cd](http://ss64.com/bash/cd.html)
Change Directory
[cfdisk](http://ss64.com/bash/cfdisk.html)
Partition table manipulator for Linux
[chgrp](http://ss64.com/bash/chgrp.html)
Change group ownership
[chmod](http://ss64.com/bash/chmod.html)
Change access permissions
[chown](http://ss64.com/bash/chown.html)
Change file owner and group
[chroot](http://ss64.com/bash/chroot.html)
Run a command with a different root directory
[chkconfig](http://ss64.com/bash/chkconfig.html)
System services (runlevel)
[cksum](http://ss64.com/bash/cksum.html)
Print CRC checksum and byte counts
clear Clear terminal screen
[cmp](http://ss64.com/bash/cmp.html)
Compare two files
[comm](http://ss64.com/bash/comm.html)
Compare two sorted files line by line
[command](http://ss64.com/bash/command.html)
Run a command - ignoring shell functions
[continue](http://ss64.com/bash/continue.html)
Resume the next iteration of a loop
[cp](http://ss64.com/bash/cp.html)
Copy one or more files to another location
[cron](http://ss64.com/bash/cron.html)
Daemon to execute scheduled commands
[crontab](http://ss64.com/bash/crontab.html)
Schedule a command to run at a later time
[csplit](http://ss64.com/bash/csplit.html)
Split a file into context-determined pieces
[cut](http://ss64.com/bash/cut.html)
Divide a file into several parts
d
[date](http://ss64.com/bash/date.html)
Display or change the date & time
[dc](http://ss64.com/bash/dc.html)
Desk Calculator
[dd](http://ss64.com/bash/dd.html)
Convert and copy a file, write disk headers, boot records
[ddrescue](http://ss64.com/bash/ddrescue.html)
Data recovery tool
[declare](http://ss64.com/bash/declare.html)
Declare variables and give them attributes
[df](http://ss64.com/bash/df.html)
Display free disk space
[diff](http://ss64.com/bash/diff.html)
Display the differences between two files
[diff3](http://ss64.com/bash/diff3.html)
Show differences among three files
[dig](http://ss64.com/bash/dig.html)
DNS lookup
[dir](http://ss64.com/bash/dir.html)
Briefly list directory contents
[dircolors](http://ss64.com/bash/dircolours.html)
Colour setup for `ls'
[dirname](http://ss64.com/bash/dirname.html)
Convert a full pathname to just a path
[dirs](http://ss64.com/bash/dirs.html)
Display list of remembered directories
[dmesg](http://ss64.com/bash/dmesg.html)
Print kernel & driver messages
[du](http://ss64.com/bash/du.html)
Estimate file space usage
e
[echo](http://ss64.com/bash/echo.html)
Display message on screen
[egrep](http://ss64.com/bash/egrep.html)
Search file(s) for lines that match an extended expression
[eject](http://ss64.com/bash/eject.html)
Eject removable media
[enable](http://ss64.com/bash/enable.html)
Enable and disable builtin shell commands
[env](http://ss64.com/bash/env.html)
Environment variables
ethtool Ethernet card settings
[eval](http://ss64.com/bash/eval.html)
Evaluate several commands/arguments
[exec](http://ss64.com/bash/exec.html)
Execute a command
[exit](http://ss64.com/bash/exit.html)
Exit the shell
[expect](http://en.wikipedia.org/wiki/Expect)
Automate arbitrary applications accessed over a terminal
[expand](http://ss64.com/bash/expand.html)
Convert tabs to spaces
[export](http://ss64.com/bash/export.html)
Set an environment variable
[expr](http://ss64.com/bash/expr.html)
Evaluate expressions
f
[false](http://ss64.com/bash/false.html)
Do nothing, unsuccessfully
[fdformat](http://ss64.com/bash/fdformat.html)
Low-level format a floppy disk
[fdisk](http://ss64.com/bash/fdisk.html)
Partition table manipulator for Linux
[fg](http://ss64.com/bash/fg.html)
Send job to foreground
[fgrep](http://ss64.com/bash/fgrep.html)
Search file(s) for lines that match a fixed string
file Determine file type
[find](http://ss64.com/bash/find.html)
Search for files that meet a desired criteria
[fmt](http://ss64.com/bash/fmt.html)
Reformat paragraph text
[fold](http://ss64.com/bash/fold.html)
Wrap text to fit a specified width.
[for](http://ss64.com/bash/for.html)
Expand words
, and execute commands
format Format disks or tapes
free Display memory usage
[fsck](http://ss64.com/bash/fsck.html)
File system consistency check and repair
ftp File Transfer Protocol
[function](http://ss64.com/bash/function.html)
Define Function Macros
[fuser](http://ss64.com/bash/fuser.html)
Identify/kill the process that is accessing a file
g
[gawk](http://ss64.com/bash/awk.html)
Find and Replace text within file(s)
[getopts](http://ss64.com/bash/getopts.html)
Parse positional parameters
[grep](http://ss64.com/bash/grep.html)
Search file(s) for lines that match a given pattern
[groups](http://ss64.com/bash/groups.html)
Print group names a user is in
[gzip](http://ss64.com/bash/gzip.html)
Compress or decompress named file(s)
h
[hash](http://ss64.com/bash/hash.html)
Remember the full pathname of a name argument
[head](http://ss64.com/bash/head.html)
Output the first part of file(s)
[history](http://ss64.com/bash/history.html)
Command History
[hostname](http://ss64.com/bash/hostname.html)
Print or set system name
i
[id](http://ss64.com/bash/id.html)
Print user and group id's
[if](http://ss64.com/bash/if.html)
Conditionally perform a command
[ifconfig](http://ss64.com/bash/ifconfig.html)
Configure a network interface
[ifdown](http://ss64.com/bash/ifup.html)
Stop a network interface
[ifup](http://ss64.com/bash/ifup.html)
Start a network interface up
[import](http://ss64.com/bash/import.html)
Capture an X server screen and save the image to file
[install](http://ss64.com/bash/install.html)
Copy files and set attributes
j
[join](http://ss64.com/bash/join.html)
Join lines on a common field
k
[kill](http://ss64.com/bash/kill.html)
Stop a process from running
killall Kill processes by name
l
[less](http://ss64.com/bash/less.html)
Display output one screen at a time
[let](http://ss64.com/bash/let.html)
Perform arithmetic on shell variables
[ln](http://ss64.com/bash/ln.html)
Make links between files
[local](http://ss64.com/bash/local.html)
Create variables
[locate](http://ss64.com/bash/locate.html)
Find files
[logname](http://ss64.com/bash/logname.html)
Print current login name
[logout](http://ss64.com/bash/logout.html)
Exit a login shell
[look](http://ss64.com/bash/look.html)
Display lines beginning with a given string
[lpc](http://ss64.com/bash/lpc.html)
Line printer control program
[lpr](http://ss64.com/bash/lpr.html)
Off line print
lprint Print a file
lprintd Abort a print job
lprintq List the print queue
[lprm](http://ss64.com/bash/lprm.html)
Remove jobs from the print queue
[ls](http://ss64.com/bash/ls.html)
List information about file(s)
[lsof](http://ss64.com/bash/lsof.html)
List open files
m
make Recompile a group of programs
[man](http://ss64.com/bash/man.html)
Help manual
[mkdir](http://ss64.com/bash/mkdir.html)
Create new folder(s)
[mkfifo](http://ss64.com/bash/mkfifo.html)
Make FIFOs (named pipes)
mkisofs Create an hybrid ISO9660/JOLIET/HFS filesystem
[mknod](http://ss64.com/bash/mknod.html)
Make block or character special files
[more](http://ss64.com/bash/more.html)
Display output one screen at a time
[mount](http://ss64.com/bash/mount.html)
Mount a file system
[mtools](http://ss64.com/bash/mtools.html)
Manipulate MS-DOS files
[mv](http://ss64.com/bash/mv.html)
Move or rename files or directories
[mmv](http://ss64.com/bash/mmv.html)
Mass Move and rename (files)
n
netstat Networking information
[nice](http://ss64.com/bash/nice.html)
Set the priority of a command or job
[nl](http://ss64.com/bash/nl.html)
Number lines and write files
[nohup](http://ss64.com/bash/nohup.html)
Run a command immune to hangups
[nslookup](http://ss64.com/bash/nslookup.html)
Query Internet name servers interactively
o
[open](http://ss64.com/bash/open.html)
Open a file in its default application
[op](http://ss64.com/bash/op.html)
Operator access
p
[passwd](http://ss64.com/bash/passwd.html)
Modify a user password
[paste](http://ss64.com/bash/paste.html)
Merge lines of files
pathchk Check file name portability
[ping](http://ss64.com/bash/ping.html)
Test a network connection
[pkill](http://ss64.com/bash/pkill.html)
Stop processes from running
[popd](http://ss64.com/bash/popd.html)
Restore the previous value of the current directory
[pr](http://ss64.com/bash/pr.html)
Prepare files for printing
printcap Printer capability database
printenv Print environment variables
[printf](http://ss64.com/bash/printf.html)
Format and print data
[ps](http://ss64.com/bash/ps.html)
Process status
[pushd](http://ss64.com/bash/pushd.html)
Save and then change the current directory
[pwd](http://ss64.com/bash/pwd.html)
Print Working Directory
q
[quota](http://ss64.com/bash/quota.html)
Display disk usage and limits
[quotacheck](http://ss64.com/bash/quotacheck.html)
Scan a file system for disk usage
[quotactl](http://ss64.com/bash/quotactl.html)
Set disk quotas
r
[ram](http://ss64.com/bash/ram.html)
ram disk device
[rcp](http://ss64.com/bash/rcp.html)
Copy files between two machines
[read](http://ss64.com/bash/read.html)
read a line from standard input
[readonly](http://ss64.com/bash/readonly.html)
Mark variables/functions as readonly
reboot Reboot the system
renice Alter priority of running processes
remsync Synchronize remote files via email
[return](http://ss64.com/bash/return.html)
Exit a shell function
[rev](http://ss64.com/bash/rev.html)
Reverse lines of a file
[rm](http://ss64.com/bash/rm.html)
Remove files
[rmdir](http://ss64.com/bash/rmdir.html)
Remove folder(s)
[rsync](http://ss64.com/bash/rsync.html)
Remote file copy (Synchronize file trees)
s
[screen](http://ss64.com/bash/screen.html)
Multiplex terminal, run remote shells via ssh
[scp](http://ss64.com/bash/scp.html)
Secure copy (remote file copy)
[sdiff](http://ss64.com/bash/sdiff.html)
Merge two files interactively
[sed](http://ss64.com/bash/sed.html)
Stream Editor
[select](http://ss64.com/bash/select.html)
Accept keyboard input
[seq](http://ss64.com/bash/seq.html)
Print numeric sequences
[set](http://ss64.com/bash/set.html)
Manipulate shell variables and functions
sftp Secure File Transfer Program
[shift](http://ss64.com/bash/shift.html)
Shift positional parameters
[shopt](http://ss64.com/bash/shopt.html)
Shell Options
[shutdown](http://ss64.com/bash/shutdown.html)
Shutdown or restart linux
[sleep](http://ss64.com/bash/sleep.html)
Delay for a specified time
[slocate](http://ss64.com/bash/slocate.html)
Find files
[sort](http://ss64.com/bash/sort.html)
Sort text files
[source](http://ss64.com/bash/source.html)
Run commands from a file `.'
[split](http://ss64.com/bash/split.html)
Split a file into fixed-size pieces
[ssh](http://en.wikipedia.org/wiki/Secure_Shell)
Secure Shell client (remote login program)
strace Trace system calls and signals
[su](http://ss64.com/bash/su.html)
Substitute user identity
[sudo](http://ss64.com/bash/sudo.html)
Execute a command as another user
[sum](http://ss64.com/bash/sum.html)
Print a checksum for a file
[symlink](http://ss64.com/bash/symlink.html)
Make a new name for a file
[sync](http://ss64.com/bash/sync.html)
Synchronize data on disk with memory
t
[tail](http://ss64.com/bash/tail.html)
Output the last part of files
[tar](http://ss64.com/bash/tar.html)
Tape ARchiver
[tee](http://ss64.com/bash/tee.html)
Redirect output to multiple files
[test](http://ss64.com/bash/test.html)
Evaluate a conditional expression
[time](http://ss64.com/bash/time.html)
Measure Program running time
[times](http://ss64.com/bash/times.html)
User and system times
[touch](http://ss64.com/bash/touch.html)
Change file timestamps
[top](http://ss64.com/bash/top.html)
List processes running on the system
[traceroute](http://ss64.com/bash/traceroute.html)
Trace Route to Host
trap Run a command when a signal is set(bourne)
[tr](http://ss64.com/bash/tr.html)
Translate, squeeze, and/or delete characters
[true](http://ss64.com/bash/true.html)
Do nothing, successfully
[tsort](http://ss64.com/bash/tsort.html)
Topological sort
[tty](http://ss64.com/bash/tty.html)
Print filename of terminal on stdin
[type](http://ss64.com/bash/type.html)
Describe a command
u
[ulimit](http://ss64.com/bash/ulimit.html)
Limit user resources
[umask](http://ss64.com/bash/umask.html)
Users file creation mask
umount Unmount a device
[unalias](http://ss64.com/bash/alias.html)
Remove an alias
[uname](http://ss64.com/bash/uname.html)
Print system information
[unexpand](http://ss64.com/bash/unexpand.html)
Convert spaces to tabs
[uniq](http://ss64.com/bash/uniq.html)
Uniquify files
[units](http://ss64.com/bash/units.html)
Convert units from one scale to another
[unset](http://ss64.com/bash/unset.html)
Remove variable or function names
[unshar](http://ss64.com/bash/unshar.html)
Unpack shell archive scripts
[until](http://ss64.com/bash/until.html)
Execute commands (until error)
[useradd](http://ss64.com/bash/useradd.html)
Create new user account
[usermod](http://ss64.com/bash/usermod.html)
Modify user account
[users](http://ss64.com/bash/users.html)
List users currently logged in
[uuencode](http://ss64.com/bash/uuencode.html)
Encode a binary file
[uudecode](http://ss64.com/bash/uuencode.html)
Decode a file created by uuencode
v
v Verbosely list directory contents (`ls -l -b')
vdir Verbosely list directory contents (`ls -l -b')
[vi](http://ss64.com/bash/vi.html)
Text Editor
[vmstat](http://ss64.com/bash/vmstat.html)
Report virtual memory statistics
w
[watch](http://ss64.com/bash/watch.html)
Execute/display a program periodically
[wc](http://ss64.com/bash/wc.html)
Print byte, word, and line counts
[whereis](http://ss64.com/bash/whereis.html)
Report all known instances of a command
[which](http://ss64.com/bash/which.html)
Locate a program file in the user's path.
[while](http://ss64.com/bash/while.html)
Execute commands
[who](http://ss64.com/bash/who.html)
Print all usernames currently logged in
[whoami](http://ss64.com/bash/whoami.html)
Print the current user id and name (`id -un')
Wget Retrieve web pages or files via HTTP, HTTPS or FTP
[write](http://ss64.com/bash/write.html)
Send a message to another user
x
[xargs](http://ss64.com/bash/xargs.html)
Execute utility, passing constructed argument list(s)
[yes](http://ss64.com/bash/yes.html)
Print a string until interrupted
[.](http://ss64.com/bash/source.html)
Run a command script in the current shell
[###](http://ss64.com/bash/rem.html)
Comment / Remark
进入 sed
如果可以使编辑文件的过程自动化,以便用“批处理”方式编辑文件,甚至编写可以对现有文件进行复杂更改的脚本,那将太好了。幸运的是,对于这种情况,有一种更好的方法
– 这种更好的方法称为 “sed”。
sed 是一种几乎包括在所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed
有许多很好的特性。首先,它相当小巧,通常要比您所喜爱的脚本语言小很多倍。其次,因为 sed
是一种流编辑器,所以,它可以对从如管道这样的标准输入接收的数据进行编辑。因此,无需将要编辑的数据存储在磁盘上的文件中。因为可以轻易将数据管道输出 到
sed,所以,将 sed 用作强大的 shell 脚本中长而复杂的管道很容易。试一下用您所喜爱的编辑器去那样做。
GNU sed
对 Linux 用户来说幸运的是,最好的 sed 版本之一恰好是 GNU sed,其当前版本是 3.02。每一个 Linux
发行版都有(或至少应该有)GNU sed。GNU sed 之所以流行不仅因为可以自由分发其源代码,还因为它恰巧有许多对 POSIX sed
标准便利、省时的扩展。另外,GNU 没有 sed 早期专门版本的很多限制,如行长度限制 – GNU 可以轻松处理任意长度的行。
最新的 GNU sed
在 研究这篇文章之时我注意到:几个在线 sed 爱好者提到 GNU sed
3.02a。奇怪的是,在ftp.gnu.org(有关这些链接,请参阅参考资料)上找不到 sed
3.02a,所以,我只得在别处寻找。我在alpha.gnu.org 的 /pub/sed
中找到了它。于是我高兴地将其下载、编译然后安装,而几分钟后我发现最新的 sed 版本却是 3.02.80 – 可在alpha.gnu.org 上
3.02a 源代码旁边找到其源代码。安装完 GNU sed 3.02.80 之后,我就完全准备好了。
正确的 sed
在 本系列中,将使用 GNU sed 3.02.80。在即将出现的本系列后续文章中,某些(但非常少)最高级的示例将不能在 GNU sed 3.02 或
3.02a 中使用。如果您使用的不是 GNU sed,那么结果可能会不同。现在为什么不花些时间安装 GNU sed 3.02.80
呢?那样,不仅可以为本系列的余下部分作好准备,而且还可以使用可能是目前最好的 sed。
sed 示例
sed 通过对输入数据执行任意数量用户指定的编辑操作(“命令”)来工作。sed 是基于行的,因此按顺序对每一行执行命令。然后,sed 将其结果写入标准输出
(stdout),它不修改任何输入文件。
让我们看一些示例。头几个会有些奇怪,因为我要用它们演示 sed 如何工作,而不是执行任何有用的任务。然而,如果您是 sed
新手,那么理解它们是十分重要的。下面是第一个示例:
进入 sed
如果可以使编辑文件的过程自动化,以便用“批处理”方式编辑文件,甚至编写可以对现有文件进行复杂更改的脚本,那将太好了。幸运的是,对于这种情况,有一种更好的方法
– 这种更好的方法称为 “sed”。
sed 是一种几乎包括在所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed
有许多很好的特性。首先,它相当小巧,通常要比您所喜爱的脚本语言小很多倍。其次,因为 sed
是一种流编辑器,所以,它可以对从如管道这样的标准输入接收的数据进行编辑。因此,无需将要编辑的数据存储在磁盘上的文件中。因为可以轻易将数据管道输出 到
sed,所以,将 sed 用作强大的 shell 脚本中长而复杂的管道很容易。试一下用您所喜爱的编辑器去那样做。
GNU sed
对 Linux 用户来说幸运的是,最好的 sed 版本之一恰好是 GNU sed,其当前版本是 3.02。每一个 Linux
发行版都有(或至少应该有)GNU sed。GNU sed 之所以流行不仅因为可以自由分发其源代码,还因为它恰巧有许多对 POSIX sed
标准便利、省时的扩展。另外,GNU 没有 sed 早期专门版本的很多限制,如行长度限制 – GNU 可以轻松处理任意长度的行。
最新的 GNU sed
在 研究这篇文章之时我注意到:几个在线 sed 爱好者提到 GNU sed
3.02a。奇怪的是,在ftp.gnu.org(有关这些链接,请参阅参考资料)上找不到 sed
3.02a,所以,我只得在别处寻找。我在alpha.gnu.org 的 /pub/sed
中找到了它。于是我高兴地将其下载、编译然后安装,而几分钟后我发现最新的 sed 版本却是 3.02.80 – 可在alpha.gnu.org 上
3.02a 源代码旁边找到其源代码。安装完 GNU sed 3.02.80 之后,我就完全准备好了。
正确的 sed
在 本系列中,将使用 GNU sed 3.02.80。在即将出现的本系列后续文章中,某些(但非常少)最高级的示例将不能在 GNU sed 3.02 或
3.02a 中使用。如果您使用的不是 GNU sed,那么结果可能会不同。现在为什么不花些时间安装 GNU sed 3.02.80
呢?那样,不仅可以为本系列的余下部分作好准备,而且还可以使用可能是目前最好的 sed。
sed 示例
sed 通过对输入数据执行任意数量用户指定的编辑操作(“命令”)来工作。sed 是基于行的,因此按顺序对每一行执行命令。然后,sed 将其结果写入标准输出
(stdout),它不修改任何输入文件。
让我们看一些示例。头几个会有些奇怪,因为我要用它们演示 sed 如何工作,而不是执行任何有用的任务。然而,如果您是 sed
新手,那么理解它们是十分重要的。下面是第一个示例:
规则表达式混乱
目前为止,我们只执行了简单的字符串替换。虽然这很方便,但是我们还可以匹配规则表达式。例如,以下 sed 命令将匹配从 ‘<’ 开始、到 ‘>’
结束、并且在其中包含任意数量字符的短语。下例将删除该短语(用空字符串替换):
1
$ sed -e 's/<.*>//g' myfile.html
这 是要从文件除去 HTML 标记的第一个很好的 sed 脚本尝试,但是由于规则表达式的特有规则,它不会很好地工作。原因何在?当 sed
试图在行中匹配规则表达式时,它要在行中查找最长的匹配。在我的前一篇 sed 文章中,这不成问题,因为我们使用的是 ‘d’ 和 ‘p’
命令,这些命令总要删除或打印整行。但是,在使用 ‘s///’
命令时,确实有很大不同,因为规则表达式匹配的整个部分将被目标字符串替换,或者,在本例中,被删除。这意味着,上例将把下行:
This is what I meant.
变成:
meant.
我们要的不是这个,而是:
This is what I meant.
幸 运的是,有一种简便方法来纠正该问题。我们不输入“‘<’ 字符后面跟有一些字符并以 ‘>’ 字符结束”的规则表达式,而只需输入一个“‘<’
字符后面跟有任意数量非 ‘>’ 字符并以 ‘>’ 字符结束”的规则表达式。这将与最短、而不是最长的可能性匹配。新命令如下:
1
$ sed -e 's/<[^>]*>//g' myfile.html
在上例中,‘[^>]’ 指定“非 ‘>’”字符,其后的 ‘*’ 完成该表达式以表示“零或多个非 ‘>’ 字符”。对几个 html
文件测试该命令,将它们管道输出到 “more”,然后仔细查看其结果。
高级替换功能
我们已经看到如何执行简单甚至有些复杂的直接替换,但是 sed
还可以做更多的事。实际上可以引用匹配规则表达式的部分或全部,并使用这些部分来构造替换字符串。作为示例,假设您正在回复一条消息。下例将在每一行前面加上短语
"ralph said: ":
1 2
$ sed -e 's/.*/ralph said: &/' origmsg.txt
输出如下:
ralph said: Hiya Jim, ralph said: ralph said:
I sure like this sed stuff! ralph said:
该例的替换字符串中使用了 ‘&’ 字符,该字符告诉 sed 插入整个匹配的规则表达式。因此,可以将与 ‘.*’
匹配的任何内容(行中的零或多个字符的最大组或整行)插入到替换字符串中的任何位置,甚至多次插入。这非常好,但 sed 甚至更强大。
foo bar oni eeny meeny miny larry curly moe jimmy the weasel
现在假设要编写一个 sed 脚本,该脚本将把 “eeny meeny miny” 替换成 “Victor eeny-meeny Von miny”
等等。要这样做,首先要编写一个由空格分隔并与三个字符串匹配的规则表达式。
Victor foo-bar Von oni Victor eeny-meeny Von miny Victor larry-curly Von moe
Victor jimmy-the Von weasel
随着对 sed 越来越熟悉,您可以花最小力气来进行相当强大的文本处理。您可能想如何使用熟悉的脚本语言来处理这种问题 –
能用一行代码轻易实现这样的解决方案吗?
组合使用
在 开始创建更复杂的 sed 脚本时,需要有输入多个命令的能力。有几种方法这样做。首先,可以在命令之间使用分号。例如,以下命令系列使用 ‘=’ 命令和
‘p’ 命令,‘=’ 命令告诉 sed 打印行号,‘p’ 命令明确告诉 sed 打印该行(因为处于 ‘-n’ 模式)。
一个地址的多个命令 有时,可能要指定应用到一个地址的多个命令。这在执行许多 's///' 以变换源文件中的字和语法时特别方便。要对一个地址执行多个命令,可在文件中输入 sed 命令,然后使用 '{ }' 字符将这些命令分组,如下所示: 1,20{ s/[Ll]inux/GNU//Linux/g s/samba/Samba/g s/posix/POSIX/g } 上例将把三个替换命令应用到第 1 行到第 20 行(包括这两行)。还可以使用规则表达式地址或者二者的组合: 1,/^END/{ s/[Ll]inux/GNU//Linux/g s/samba/Samba/g s/posix/POSIX/g p } 该例将把 '{ }' 之间的所有命令应用到从第 1 行开始,到以字母 "END" 开始的行结束(如果在源文件中没发现 "END",则到文件结束)的所有行。 附加、插入和更改行 既然在单独的文件中编写 sed 脚本,我们可以利用附加、插入和更改行命令。这些命令将在当前行之后插入一行,在当前行之前插入一行,或者替换模式空间中的当前行。 它们也可以用来将多行插入到输出。插入行命令用法如下: i/ This line will be inserted before each line 如果不为该命令指定地址,那么它将应用到每一行,并产生如下的输出: This line will be inserted before each line line 1 here This line will be inserted before each line line 2 here This line will be inserted before each line line 3 here This line will be inserted before each line line 4 here 如果要在当前行之前插入多行,可以通过在前一行之后附加一个反斜杠来添加附加行,如下所示: i/ insert this line/ and this one/ and this one/ and, uh, this one too. 附加命令的用法与之类似,但是它将把一行或多行插入到模式空间中的当前行之后。其用法如下: a/ insert this line after each line. Thanks!  另一方面,“更改行”命令将实际替换模式空间中的当前行,其用法如下: c/ You're history, original line! Muhahaha! 因为附加、插入和更改行命令需要在多行输入,所以将把它们输入到一个文本 sed 脚本中,然后通过使用 '-f' 选项告诉 sed 执行它们。使用其它方法将命令传递给 sed 会出现问题。
规则表达式将与行的末尾匹配,而 '/r' 告诉 sed 在其之前插入一个回车。在换行之前插入回车,立即,每一行就以 CR/LF
1 2 3 4 5 6 7
结束。请注意,仅当使用 GNU sed 3.02.80 或以后的版本时,才会用 CR 替换 '/r'。如果还没有安装 GNU sed 3.02.80,请在我的第一篇 sed 文章中查看如何这样做的说明。 我已记不清有多少次在下载一些示例脚本或 C 代码之后,却发现它是 DOS/Windows 格式。虽然很多程序不在乎 DOS/Windows 格式的 CR/LF 文本文件,但是有几个程序却在乎 -- 最著名的是 bash,只要一遇到回车,它就会出问题。以下 sed 调用将把 DOS/Windows 格式的文本转换成可信赖的 UNIX 格式:
$ sed -e ‘s/.$//’ mydos.txt > myunix.txt
1 2 3 4 5 6 7 8 9 10 11 12
除了输出中每行的最末字符,那么,您就指定了已经是 UNIX 格式的文本文件。也就没必要那样做了! 反转行 下 面是另一个方便的小脚本。与大多数 Linux 发行版中包括的 "tac" 命令一样,该脚本将反转文件中行的次序。"tac" 这个名称可能会给人以误导,因为 "tac" 不反转行中字符的位置(左和右),而是反转文件中行的位置(上和下)。用 "tac" 处理以下文件: foo bar oni ....将产生以下输出: oni bar foo 可以用以下 sed 脚本达到相同目的:
$ sed -e ‘1!G;h;$!d’ forward.txt > backward.txt
反转解释
首 先,该脚本包含三个由分号隔开的单独 sed 命令:'1!G'、'h' 和 '\$!d'。现在,需要好好理解用于第一个和第三个命令的地址。如果第一个命令是
'1G',则 'G' 命令将只应用第一行。然而,还有一个 '!' 字符 -- 该 '!' 字符忽略该地址,即,'G'
命令将应用到除第一行之外的所有行。'\$!d' 命令与之类似。如果命令是 '\$d',则将只把 'd' 命令应用到文件中的最后一行('\$'
地址是指定最后一行的简单方式)。然而,有了 '!' 之后,'\$!d' 将把 'd'
命令应用到除最后一行之外的所有行。现在,我们所要理解的是这些命令本身做什么。
当对上面的文本文件执行反转脚本时,首先执行的命令是 'h'。该命令告诉 sed
将模式空间(保存正在处理的当前行的缓冲区)的内容复制到保留空间(临时缓冲区)。然后,执行 'd' 命令,该命令从模式空间中删除
"foo",以便在对这一行执行完所有命令之后不打印它。
现在,第二行。在将 "bar" 读入模式空间之后,执行 'G' 命令,该命令将保留空间的内容 ("foo/n") 附加到模式空间
("bar/n"),使模式空间的内容为 "bar/n/foo/n"。'h' 命令将该内容放回保留空间保护起来,然后,'d'
从模式空间删除该行,以便不打印它。
对于最后的 "oni" 行,除了不删除模式空间的内容(由于 'd' 之前的 '\$!')以及将模式空间的内容(三行)打印到标准输出之外,重复同样的步骤。
现在,要用 sed 执行一些强大的数据转换。
sed QIF 魔法
过去几个星期,我一直想买一份 Quicken 来结算我的银行帐户。Quicken
是一个非常好的金融程序,当然会成功地完成这项工作。但是,经过考虑之后,我觉得自己可以轻易编写某个软件来结算我的支票簿。我想,毕竟,我是个软件开发人员!
我 开发了一个很好的小型支票簿结算程序(使用 awk),它通过分析包含我的所有交易的文本文件的语法来计算余额。略微调整之后,我将其改进,以便可以象
Quicken 那样跟踪不同的贷款和借款类别。但是,我还要添加一个特性。最近,我将帐户转移到一家有联机 Web 帐户界面的银行。有一天,我注意到,这家银行的
Web 站点允许以 Quicken 的 .QIF 格式下载我的帐户信息。我马上觉得,如果可以将该信息转换成文本格式,那就太棒了。
两种格式的故事
在查看 QIF 格式之前,先看一下我的 checkbook.txt 格式:
28 Aug 2000 food - - Y Supermarket 30.94 25 Aug 2000 watr - 103 Y Check 103
52.86
在我的文件中,所有字段都由一个或多个制表符分开,每个交易占据一行。日期之后的下一个字段列 出支出类型(如果是收入项,则为
"-")。第三个字段列出收入类型(如果是支出项,则为 "-")。然后,是一个支票号字段(如果为空,则还是 "-"),一个交易完成字段("Y" 或
"N"),一个注释和一个美元金额字段。现在,让我们看一下 QIF 格式。当用文本查看器查看下载的 QIF 文件时,它看起来如下:
!Type:Bank D08/28/2000 T-8.15 N PCHECKCARD SUPERMARKET ^ D08/28/2000 T-8.25 N
PCHECKCARD PUNJAB RESTAURANT ^ D08/28/2000 T-17.17 N PCHECKCARD SUPERMARKET
浏览过文件之后,不难猜出其格式 -- 忽略第一行,其余的格式如下:
D<数据>
T<交易量>
N<支票号>
P<描述>
^ (这是字段分隔符)
开始处理
在处理象这样重要的 sed 项目时,不要气馁 -- sed 允许您将数据逐渐修改成最终形式。在进行当中,可以继续细化 sed
脚本,直到输出与预期的完全一样为止。无需在试第一次时就保证其完全正确。
要开始,首先创建一个名为 "qiftrans.sed" 的文件,然后开始修改数据:
1d /^^/d s/[[:cntrl:]]//g
第一个 '1d' 命令删除第一行,第二个命令从输出除去那些讨厌的 '^' 字符。最后一行除去文件中可能存在的任何控制字符。既然在处理外来文件格式,我想消除在
中途遇到任何控制字符的风险。到目前为止,一切顺利。现在,要向该基本脚本中添加一些处理功能:
1d /^^/d s/[[:cntrl:]]//g /^D/ {
s/^D/(.*/)//1/tOUTY/tINNY/t/
s/^01/Jan/ s/^02/Feb/
s/^03/Mar/ s/^04/Apr/
s/^05/May/ s/^06/Jun/
s/^07/Jul/ s/^08/Aug/
s/^09/Sep/ s/^10/Oct/
s/^11/Nov/ s/^12/Dec/
s:^/(.*/)//(.*/)//(.*/):/2 /1 /3: }
首先,添加一个 '/^D/' 地址,以便 sed 只在遇到 QIF 数据字段的第一个字符 'D' 时才开始处理。当 sed
将这样一行读入其模式空间时,将按顺序执行花括号中的所有命令。
花括号中的第一个命令将把如下行:
D08/28/2000
变换成:
08/28/2000 OUTY INNY
当然,现在的格式还不完美,但没关系。我们将在进行过程中逐渐细化模式空间的内容。后面 12
行的最后效果是将数据变换成三个字母的格式,最后一行从数据中除去三个斜杠。最后得到这一行:
Aug 28 2000 OUTY INNY
OUTY 和 INNY 字段是占位符,以后将被替换。现在还不能确定它们,因为如果美元金额为负,将把 OUTY 和 INNY 设置成 "misc" 和
"-",但是,如果美元金额为正,将分别把它们更改成 "-" 和 "inco"。既然还没有读入美元金额,所以,需要暂时使用占位符。
细化
现在进一步细化:
1d /^^/d s/[[:cntrl:]]//g /^D/ {
s/^D/(.*/)//1/tOUTY/tINNY/t/
s/^01/Jan/ s/^02/Feb/
s/^03/Mar/ s/^04/Apr/
s/^05/May/ s/^06/Jun/
s/^07/Jul/ s/^08/Aug/
s/^09/Sep/ s/^10/Oct/
s/^11/Nov/ s/^12/Dec/
s:^/(.*/)//(.*/)//(.*/):/2 /1 /3:
N N N
s//nT/(.*/)/nN/(.*/)/nP/(.*/)/NUM/2NUM/t/tY/t/t/3/tAMT/1AMT/
s/NUMNUM/-/ s/NUM/([0-9]*/)NUM//1/
s//([0-9]/),//1/ }
后七行有些复杂,所以将详细讨论它们。首先,连续使用三个 'N' 命令。'N' 命令告诉 sed 将下一行读入输入中,然后将其附加到当前模式空间。这三个
'N' 命令导致将下三行附加到当前模式空间缓冲区,现在这一行看起来如下:
28 Aug 2000 OUTY INNY /nT-8.15/nN/nPCHECKCARD SUPERMARKET
sed 的模式空间变得很难看 -- 需要除去额外的新行,并执行某些附加的格式化。要这样做,将使用替代命令。要匹配的模式为:
'/nT.*/nN.*/nP.*'
这 将与后面依次跟有
'T'、零或多个字符、新行、'N'、任何数量的字符、新行、'P'、以及任何数量字符的新行匹配。呀!这个规则表达式将与刚刚附加到模式空间的三行的全
部内容匹配。但我们要重新格式化该区域,而不是整个替换它。美元金额、支票号(如果有的话)和描述需要出现在替换字符串中。要这样做,我们用带有反斜杠的
圆括号括起那些“感兴趣部分”,以便可以在替换字符串中引用它们(使用 '/1'、'/2/ 和 '/3' 来告诉 sed 将它们插入到何处)。以下是最后的命令:
s//nT/(.*/)/nN/(.*/)/nP/(.*/)/NUM/2NUM/t/tY/t/t/3/tAMT/1AMT/
该命令将我们的行变换成:
28 Aug 2000 OUTY INNY NUMNUM Y CHECKCARD SUPERMARKET AMT-8.15AMT
虽 然该行正变得好一些,但是,有几件事一看就有点...啊...有趣。首先是那个愚蠢的 "NUMNUM" 字符串 -- 其目的何在?如果查看 sed
脚本的后两行,就会发现其目的,后两行将把 "NUMNUM" 替换成 "-",而把 "NUM"<number>"NUM" 替换成
<number>。如您所见,用愚蠢的标记括起支票号允许我们在该字段为空时方便地插入一个 "-"。
结束尝试
最后一行除去数字后的逗号。它把如 "3,231.00" 这样的美元金额转换成我使用的格式 "3231.00"。现在,让我们看一下最终脚本:
最终的“QIF 到文本”脚本 1d /^^/d s/[[:cntrl:]]//g /^D/ { s/^D/(.*/)//1/tOUTY/tINNY/t/
s/^01/Jan/ s/^02/Feb/ s/^03/Mar/ s/^04/Apr/ s/^05/May/
s/^06/Jun/ s/^07/Jul/ s/^08/Aug/ s/^09/Sep/ s/^10/Oct/
s/^11/Nov/ s/^12/Dec/ s:^/(.*/)//(.*/)//(.*/):/2 /1 /3:
N N N s//nT/(.*/)/nN/(.*/)/nP/(.*/)/NUM/2NUM/t/tY/t/t/3/tAMT/1AMT/
s/NUMNUM/-/ s/NUM/([0-9]*/)NUM//1/ s//([0-9]/),//1/
/AMT-[0-9]*.[0-9]*AMT/b fixnegs
s/AMT/(.*/)AMT//1/ s/OUTY/-/ s/INNY/inco/
b done :fixnegs s/AMT-/(.*/)AMT//1/ s/OUTY/misc/
s/INNY/-/ :done }
附加的十一行使用替代和一些分支功能来美化输出。首先看一下这行:
/AMT-[0-9]*.[0-9]*AMT/b fixnegs
该行包含一个格式为 "/regexp/b label" 的分支命令。如果模式空间与规则表达式匹配,sed 将分支到 fixnegs
标号。您应该可以轻易找到该标号,它在代码中为 ":fixnegs"。如果规则表达式不匹配,则以常规方式继续处理下一个命令。
既 然您理解该命令本身的工作原理,让我们看一下分支。如果看一下分支规则表达式,将看到它与后面依次跟有 '-'、任意数量的数字、一个 '.'、任意数量的数字和
'AMT' 的字符串 'AMT' 匹配。就象我确信您已猜到一样,该规则表达式专门处理负的美元金额。在这之前,用 'ATM'
括起美元金额,以便以后可以轻易找到它。因为规则表达式只与以 '-' 开始的美元金额匹配,所以,该分支只在恰巧处理借款时才发生。如果正处理贷款,应该将
OUTY 设置成 'misc',将 INNY 设置成
'-',并且应该除去贷款数量前面的负号。如果跟踪代码的流程,将看到实际情况正是这样。如果不执行分支,则用 '-' 替换 OUTY,用 'inco' 替换
INNY。完成了!现在输出行是完美的:
28 Aug 2000 misc - - Y CHECKCARD SUPERMARKET -8.15
别犯糊涂
如 您所见,只要循序渐进地解决问题,使用 sed 转换数据就没有那么难。不要试图使用一个 sed
命令或一下子解决所有问题。相反,要朝着目标逐步进行,并不断改进 sed 脚本,直到其输出正如您希望那样为止。sed
有许多功能,希望您已非常熟悉其内部工作原理并继续努力以进一步掌握它!
#!/bin/sh if [ "$SHELL" = "/bin/bash" ]; then echo"your login shell is the bash (bourne again shell)" else echo"your login shell is not bash but $SHELL" fi
#!/bin/sh SYSTEM=`uname -s` case$SYSTEMin Linux) echo"My system is Linux" echo"Do Linux stuff here..." ;; FreeBSD) echo"My system is FreeBSD" echo"Do FreeBSD stuff here..." ;; *) echo"Unknown system : $SYSTEM" echo"I don't what to do..." ;; esac echo"Do FreeBSD stuff here..." ;; *) echo"Unknown system : $SYSTEM" echo"I don't what to do..." ;; esac
select var in ... ; do break done .... now $var can be used ....
下面是一个例子:
1 2 3 4 5 6 7
#!/bin/sh echo"What is your favourite OS?" select var in"Linux""Gnu Hurd""Free BSD""Other"; do break done echo"You have selected $var"
下面是该脚本运行的结果:
What is your favourite OS?
Linux
Gnu Hurd
Free BSD
Other
#? 1
You have selected Linux
4.loop
loop表达式:
while …; do
…
done
while-loop 将运行直到表达式测试为真。will run while the expression that we test for is
true.
关键字"break" 用来跳出循环。而关键字”continue”用来不执行余下的部分而直接跳到下一个循环。
for-loop表达式查看一个字符串列表 (字符串用空格分隔) 然后将其赋给一个变量:
for var in …; do
…
done
在下面的例子中,将分别打印ABC到屏幕上:
1 2 3 4
#!/bin/sh for var in A B C ; do echo"var is $var" done
下面是一个更为有用的脚本showrpm,其功能是打印一些RPM包的统计信息:
1 2 3 4 5 6 7 8 9 10 11 12 13
#!/bin/sh # list a content summary of a number of RPM packages # USAGE: showrpm rpmfile1 rpmfile2 ... # EXAMPLE: showrpm /cdrom/RedHat/RPMS/*.rpm for rpmpackage in $*; do if [ -r "$rpmpackage" ];then echo"=============== $rpmpackage ==============" rpm -qi -p $rpmpackage else echo"ERROR: cannot read file $rpmpackage" fi done
#!/bin/sh # we have less than 3 arguments. Print the help text: if [ $# -lt 3 ] ; then cat < ren -- renames a number of files using sed regular expressions USAGE: ren 'regexp''replacement' files... EXAMPLE: rename all *.HTM files in *.html: ren 'HTM$''html' *.HTM HELP exit 0 fi OLD="$1" NEW="$2" # The shift command removes one argument from the list of # command line arguments. shift shift # $* contains now all the files: for file in $*; do if [ -f "$file" ] ; then newfile=`echo"$file" | sed "s/${OLD}/${NEW}/g"` if [ -f "$newfile" ]; then echo"ERROR: $newfile exists already" else echo"renaming $file to $newfile ..." mv"$file""$newfile" fi fi done
#!/bin/sh # vim: set sw=4 ts=4 et: help() { cat < xtitlebar -- change the name of an xterm, gnome-terminal or kde konsole USAGE: xtitlebar [-h] "string_for_titelbar" OPTIONS: -h help text EXAMPLE: xtitlebar "cvs" HELP exit 0 } # in case of error or if -h is given we call the function help: [ -z "$1" ] && help [ "$1" = "-h" ] && help # send the escape sequence to change the xterm titelbar: echo -e "33]0;$107" #
#!/bin/sh help() { cat < This is a generic command line parser demo. USAGE EXAMPLE: cmdparser -l hello -f -- -somefile1 somefile2 HELP exit 0 } while [ -n "$1" ]; do case$1in -h) help;shift 1;; # function help is called -f) opt_f=1;shift 1;; # variable opt_f is set -l) opt_l=$2;shift 2;; # -l takes an argument -> shift by 2 \--) shift;break;; # end of options -*) echo"error: no such option $1. -h for help";exit 1;; *) break;; esac done echo"opt_f is $opt_f" echo"opt_l is $opt_l" echo"first arg is $1" echo"2nd arg is $2"
您可以这样运行该脚本:
cmdparser -l hello -f – -somefile1 somefile2
返回的结果是:
opt_f is 1
opt_l is hello
first arg is -somefile1
2nd arg is somefile2
这个脚本是如何工作的呢?脚本首先在所有输入命令行参数中进行循环,将输入参数
与case表达式进行比较,如果匹配则设置一个变量并且移除该参数。根据unix系统的惯例,
首先输入的应该是包含减号的参数.
第2部分 实例
现在我们来讨论编写一个脚本的一般步骤。任何优秀的脚本都应该具有帮助和输入参数。并且写一个伪脚本(framework.sh),该脚本包含了大多数脚本都需要的框
架结构,是一个非常不错的主意。这时候,在写一个新的脚本时我们只需要执行一下copy命令:
cp framework.sh myscript
然后再插入自己的函数。
让我们再看两个例子:
二进制到十进制的转换
脚本 b2d 将二进制数 (比如 1101) 转换为相应的十进制数。这也是一个用expr命令进行数学运算的例子:
#!/bin/sh # vim: set sw=4 ts=4 et: help() { cat < b2h -- convert binary to decimal USAGE: b2h [-h] binarynum OPTIONS: -h help text EXAMPLE: b2h 111010 will return 58 HELP exit 0 } error() { # print an error and exit echo"$1" exit 1 } lastchar() { # return the last character of a string in $rval if [ -z "$1" ]; then # empty string rval="" return fi # wc puts some space behind the output this is why we need sed: numofchar=`echo -n "$1" | wc -c | sed 's/ //g' ` # now cut out the last char rval=`echo -n "$1" | cut -b $numofchar` } chop() { # remove the last character in string and return it in $rval if [ -z "$1" ]; then # empty string rval="" return fi # wc puts some space behind the output this is why we need sed: numofchar=`echo -n "$1" | wc -c | sed 's/ //g' ` if [ "$numofchar" = "1" ]; then # only one char in string rval="" return fi numofcharminus1=`expr$numofchar"-" 1` # now cut all but the last char: rval=`echo -n "$1" | cut -b 0-${numofcharminus1}` } while [ -n "$1" ]; do case$1in -h) help;shift 1;; # function help is called \--) shift;break;; # end of options -*) error "error: no such option $1. -h for help";; *) break;; esac done # The main program sum=0 weight=1 # one arg must be given: [ -z "$1" ] && help binnum="$1" binnumorig="$1" while [ -n "$binnum" ]; do lastchar "$binnum" if [ "$rval" = "1" ]; then sum=`expr"$weight""+""$sum"` fi # remove the last position in $binnum chop "$binnum" binnum="$rval" weight=`expr"$weight""*" 2` done echo"binary $binnumorig is decimal $sum"
#!/bin/sh # vim: set sw=4 ts=4 et:
ver="0.1"help()
{
cat <
rotatefile -- rotate the file name
USAGE: rotatefile [-h] filename
OPTIONS: -h help text
EXAMPLE: rotatefile out
This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1
and create an empty out-file
The max number is 10
version $ver
HELP
exit 0
}
error()
{
echo"$1"exit 1
}
while [ -n "$1" ]; docase$1in
-h) help;shift 1;;
\--) break;;
-*) echo"error: no such option $1. -h for help";exit 1;;
*) break;;
esacdone# input check: if [ -z "$1" ] ; then
error "ERROR: you must specify a file, use -h for help"fi
filen="$1"# rename any .1 , .2 etc file: for n in 9 8 7 6 5 4 3 2 1; doif [ -f "$filen.$n" ]; then
p=`expr$n + 1`
echo"mv $filen.$n$filen.$p"mv$filen.$n$filen.$pfidone# rename the original file: if [ -f "$filen" ]; thenecho"mv $filen$filen.1"mv$filen$filen.1
fiechotouch$filentouch$filen
这个脚本是如何工作的呢?在检测用户提供了一个文件名以后,我们进行一个9到1的循环。文件9被命名为10,文件8重命名为9等等。循环完成之后,我们将原始文件命名
为文件1同时建立一个与原始文件同名的空文件。
调试
最简单的调试命令当然是使用echo命令。您可以使用echo在任何怀疑出错的地方打印任何变量值。这也是绝大多数的shell程序员要花费80%的时间来调试程序的
原因。Shell程序的好处在于不需要重新编译,插入一个echo命令也不需要多少时间。
shell也有一个真实的调试模式。如果在脚本"strangescript" 中有错误,您可以这样来进行调试:
sh -x strangescript
这将执行该脚本并显示所有变量的值。
shell还有一个不需要执行脚本只是检查语法的模式。可以这样使用:
sh -n your_script
这将返回所有语法错误