Archive for the Category » linux «

星期三, 04月 29th, 2009 | Author: Zealot

今天小试了一把nginx,用apt装上后开始配置,可对着中文wiki上的文档配置时总是超出预期,出现各种问题,突然想起查看一下版本,竟然是0.4,官方已经0.7了,faint

于是用apt卸掉,结果aptfaint了。。。:

$ sudo apt-get –purge remove nginx
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following packages will be REMOVED:
nginx*
0 upgraded, 0 newly installed, 1 to remove and 116 not upgraded.
1 not fully installed or removed.
Need to get 0B of archives.
After unpacking 528kB disk space will be freed.
Do you want to continue [Y/n]?
(Reading database … 242827 files and directories currently installed.)
Removing nginx …
Stopping nginx: invoke-rc.d: initscript nginx, action “stop” failed.
dpkg: error processing nginx (–purge):
subprocess pre-removal script returned error exit status 1
Starting nginx: invoke-rc.d: initscript nginx, action “start” failed.
dpkg: error while cleaning up:
subprocess post-installation script returned error exit status 1
Errors were encountered while processing:
nginx

E: Sub-process /usr/bin/dpkg returned an error code (1)
上网搜了一把,好多都是说直接把相关文件删了,最后看到这个方法:“How to uninstall nginx with apt(
http://www.peterbe.com/plog/how-to-uninstall-nginx-with-apt)”,也就是在/etc/init.d/nginx 脚本的最前面加上exit 0,这样就强制return 0,解决了这个问题:E: “Sub-process /usr/bin/dpkg returned an error code (1)”

然后再apt-get –purge remove nginx,done

最后手动清了/var/lib/nginx/var/log/nginx

Category: linux, 程序设计  | Tags: , ,  | Leave a Comment
星期二, 04月 28th, 2009 | Author: Zealot

今天apt-get install vim-full的时候,出现了错误,详见后面。原因不清楚,估计是sun-java5-jre这个包相关的东西出了问题,彻底清除了试试:sudo apt-get –purge remove sun-java5-jre,然后重新装上。。
再来sudo apt-get install vim-full,OK。

Reading package lists…
Building dependency tree…
You might want to run `apt-get -f install’ to correct these:
The following packages have unmet dependencies:
sun-java5-jre: Depends: sun-java5-bin (= 1.5.0-14-1etch1) but it is not going to be installed or
ia32-sun-java5-bin (= 1.5.0-14-1etch1) but it is not installable
vim-full: Depends: vim-gui-common (= 1:7.0-122+1etch5) but it is not going to be installed
Depends: vim-common (= 1:7.0-122+1etch5) but 1:7.0-122+1etch3 is to be installed
Depends: vim-runtime (= 1:7.0-122+1etch5) but 1:7.0-122+1etch3 is to be installed
Depends: libart-2.0-2 (>= 2.3.16) but it is not going to be installed
Depends: libatk1.0-0 (>= 1.12.2) but it is not going to be installed
Depends: libbonobo2-0 (>= 2.13.0) but it is not going to be installed
Depends: libbonoboui2-0 (>= 2.5.4) but it is not going to be installed
Depends: libcairo2 (>= 1.2.4) but it is not going to be installed
Depends: libgconf2-4 (>= 2.13.5) but it is not going to be installed
Depends: libglib2.0-0 (>= 2.12.0) but it is not going to be installed
Depends: libgnome-keyring0 (>= 0.6.0) but it is not going to be installed
Depends: libgnome2-0 (>= 2.14.1) but it is not going to be installed
Depends: libgnomecanvas2-0 (>= 2.11.1) but it is not going to be installed
Depends: libgnomeui-0 (>= 2.13.0) but it is not going to be installed
Depends: libgnomevfs2-0 (>= 2.13.92) but it is not going to be installed
Depends: libgtk2.0-0 (>= 2.8.0) but it is not going to be installed
Depends: liborbit2 (>= 1:2.14.1) but it is not going to be installed
Depends: libpango1.0-0 (>= 1.14.8) but it is not going to be installed
Depends: libperl5.8 (>= 5.8.8) but it is not going to be installed
Depends: libruby1.8 (>= 1.8.5) but it is not going to be installed
Depends: libxcursor1 (> 1.1.2) but it is not going to be installed
Depends: libxfixes3 (>= 1:4.0.1) but it is not going to be installed
Depends: libxi6 but it is not going to be installed
Depends: libxinerama1 but it is not going to be installed
Depends: libxrandr2 but it is not going to be installed
Depends: libxrender1 but it is not going to be installed
Depends: tcl8.4 (>= 8.4.5) but it is not going to be installed

星期四, 10月 30th, 2008 | Author: Zealot

From : http://www.fire3.cn/2008/08/03/linux-howto-read-man-page.html

 
 

搜索和打印介绍不错:)

 
 

1 什么是man手册

 
 

首先,man是manual的简称,中文说法可以是手册。

 
 

在Linux世界中,许多新手请教某条命令的用法时, 好多不耐心的老手通常会用一条命令来回答这位无助的新手,而这条命令通常

就是man开头。无助的新手敲上这条命令一看究竟,在终端上顿时显示出来了一屏幕的英文,

老手的意思是,自己看看手册吗,可是看手册也是有学问的,无助的新手甚

至不知道怎么退出这条命令呢。下面我们就来讲解一下看man手册的学问。

2 从man手册中获取有用的信息

 
 

我们先以mkdir命令来解释读man手册的一些入门知识。

 
 

MKDIR(1) User Commands MKDIR(1)

 
 

NAME

mkdir – make directories

 
 

SYNOPSIS

mkdir [OPTION] DIRECTORY…

 
 

DESCRIPTION

Create the DIRECTORY(ies), if they do not already exist.

 
 

Mandatory arguments to long options are mandatory for short options too.

 
 

-m, –mode=MODE

set file mode (as in chmod), not a=rwx – umask

 
 

-p, –parents

no error if existing, make parent directories as needed

 
 

-v, –verbose

print a message for each created directory

 
 

-Z, –context=CTX

set the SELinux security context of each created directory to CTX

 
 

–help display this help and exit

 
 

–version

output version information and exit

 
 

AUTHOR

Written by David MacKenzie.

 
 

REPORTING BUGS

Report bugs to <bug-coreutils@gnu.org>.

 
 

COPYRIGHT

Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

 
 

This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

 
 

SEE ALSO

 
 

mkdir(2)

 
 

The full documentation for mkdir is maintained as a Texinfo manual. If the info and mkdir programs are properly installed at your site, the com-

 
 

mand

 
 

info coreutils ‘mkdir invocation’

 
 

should give you access to the complete manual.

 
 

首先第一行 MKDIR(1),显然,MKDIR是命令的大写,那么为什么有个(1)呢,那是因为man手册页有如下的规定:

Section         名称         说明

l         本地文档         与本特定系统有关的

1         用户命令         可由任何人启动的

2         系统调用         即由内核提供的函数

3         例程         即库函数

4         设备         即/dev目录下的特殊文件

5         文件格式描述         例如/etc/passwd

6         游戏         不用解释啦

7         杂项         例如宏命令包、惯例等

8         系统管理员工具         只能由root启动

9         其他(Linux特定的)         用来存放内核例行程序的文档

n         新文档         可能要移到更适合的领域

o         老文档         可能会在一段期限内保留

 
 

MKDIR(1)表示该命令属于Section 1,为用户命令,类似的man

apt-get会看到APT-GET(8),表示apt-get命令为系统管理工具。

 
 

“NAME”部分是该命令的名字和简单的解释,显然,在命令行中要执行该命令要使用到它的名称。

 
 

“SNOPSIS”是摘要部分,简要解释该命令如何使用,比如mkdir的摘要:

mkdir [OPTION] DIRECTORY…,读到这里便需要讲解一下了:

 
 

“OPTIONS”左右有”["和"]“,表示这些参数并不必须,但是可以使用。对应的DIRECTORY两边没有”[]“,就是必须要加的参数了。

另外,它们后面都有”…” ,表示这些参数可以重复使用多次。至于OPTIONS具体怎么用,就要看DESCRIPTION部分了。下面举几个简单的例子,并配合例子解释:

用法         解释

mkdir tmp         创建 tmp 目录

mkdir –mode=a+w tmp         创建一个模式为”a+w”的tmp目录,–mode是长参数,用法是–mode=MODE,在DESCRIPTION里说明

mkdir -m a+w tmp         创建一个模式为”a+w”的tmp目录,-m 是短参数,不用加 = 号,效果等同 –mode=MODE

mkdir -mv a+w tmp         创建一个模式为”a+w”的tmp目录,同时显示信息,verbose模式,-mv可以一起用

mkdir -v -m a+w tmp         创建一个模式为”a+w”的tmp目录,同时显示信息,verbose模式,-v后面接一个空格再用-m

3 man手册页的操作

3.1 退出man

 
 

最简单,按下”q”键

3.2 查找

 
 

如果你知道要打开的手册页,在man命令打开的手册页中可以用

“/” 键进行正则表达式的搜索。

 
 

如果不知道所要打开的手册页名称,可以用 “man

-k”命令搜索相关的手册页,比如:

 
 

man -k postscript

 
 

会给出一堆关于”postscript”的相关命令页。

3.3 打印

 
 

最简单的办法,以mkdir为例:

 
 

man -t mkdir > mkdir_man.ps

 
 

可以直接打印ps,打算发给别人打印的话,转换成pdf也比较方便:

 
 

ps2pdf mkdir_man.ps mkdir_man.pdf

Category: linux  | Tags: , , , , ,  | Leave a Comment
星期一, 10月 13th, 2008 | Author: Zealot

features of Python

From: http://stackoverflow.com/questions/101268/hidden-features-of-python

  • Chaining comparison operators:

    >>> x = 5

    >>> 1 < x < 10

    True

    >>> x < 10 < x*10 < 100

    True

    >>> 10 > x <= 9

    True

    >>> 5 == x > 4

    True

    In case you’re thinking it’s doing, ‘1 < x’, which comes out as True, and then comparing ‘True < 10′, which is also True, then no, that’s really not what happens (see the last example.) It’s really translating into ‘1 < x and x < 10′, and ‘x < 10 and 10 < x * 10 and x*10 < 100′, but with less typing and each term is only evaluated once.

  • Readable regular expressions

    In Python you can split a regular expression over multiple lines, name your matches and insert comments.

    Example verbose syntax (from Dive into Python):

    >>> pattern = “”"

        ^                   # beginning of string

        M{0,4}              # thousands – 0 to 4 M’s

        (CM|CD|D?C{0,3})    # hundreds – 900 (CM), 400 (CD), 0-300 (0 to 3 C’s),

                            #            or 500-800 (D, followed by 0 to 3 C’s)

        (XC|XL|L?X{0,3})    # tens – 90 (XC), 40 (XL), 0-30 (0 to 3 X’s),

                            #        or 50-80 (L, followed by 0 to 3 X’s)

        (IX|IV|V?I{0,3})    # ones – 9 (IX), 4 (IV), 0-3 (0 to 3 I’s),

                            #        or 5-8 (V, followed by 0 to 3 I’s)

        $                   # end of string

        “”"

    >>> re.search(pattern, ‘M’, re.VERBOSE)

    Example naming matches (from Regular Expression HOWTO)

    >>> p = re.compile(r‘(?P<word>\b\w+\b)’)

    >>> m = p.search( ‘(((( Lots of punctuation )))’ )

    >>> m.group(‘word’)

    ‘Lots’

  • Decorators

    Decorators allow to wrap a function or method in another function that can add functionality, modify arguments or results, etc. You write decorators one line above the function definition, beginning with an “at” sign (@).

    Example shows a print_args decorator that prints function’s arguments before calling it:

    >>> def print_args(function):

    >>>     def wrapper(*args, **kwargs):

    >>>         print
    ‘Arguments:’, args, kwargs

    >>>         return
    function(*args, **kwargs)

    >>>     return wrapper

     
     

    >>> @print_args

    >>> def write(text):

    >>>     print text

     
     

    >>> write(‘foo’)

    Arguments: (‘foo’,) {}

    foo

  • iter() can take a callable argument

    For instance:

    def seek_next_line(f):

        for c in iter(lambda: f.read(1),‘\n’):

            pass

    The iter(callable, until_value) calls repetitively the callable and yields its result until the callable returns _until_value_.

  • Creating generators objects

    If you write

    x=(n for n in foo if bar(n))

    you can get out the generator and assign it to x. Now it means you can do

    for n in x:

    The advantage of this is that you don’t need intermediate storage, which you would need if you did

    x = [n for n in foo if bar(n)]

    In some cases this can lead to significant speed up.

  • Futures and the “With” Statement

    There’s a special module in Python called __future__. Some new language features end up in this module for testing, and to use them you have to explicitly import them from here. One such feature which is a favorite of mine is the “with” statement, which is currently present in __future__ in version 2.5, but will be part of the language in the soon-to-be-released 2.6 and 3.0 versions.

    The reason it is in __future__ is because it makes both with and as keywords, which could break existing code.

    I have used the “with” statement in 2.5 a lot because I think it’s a very useful construct, here is a quick demo:

    from __future__ import with_statement

     
     

    with open(‘foo.txt’, ‘w’) as f:

        f.write(‘hello!’)

    What’s happening here behind the scenes, is that the “with” statement calls the special __enter__ and__exit__ methods on the file object. Exception details are also passed to __exit__ if any exception was raised from the with statement body, allowing for exception handling to happen there.

    What this does for you in this particular case is that it guarantees that the file is closed when execution falls out of scope of the “with” statement’s body, regardless if that occurs naturally or whether an exception was thrown. It is basically a way of abstracting away common error-handling code.

    Other common use cases for this include locking with threads and database transactions.

    For more information on how to use this and how to implement your own “with” statement compatible objects read PEP 343

  • The step argument in slice operators. For example:

    a = [1,2,3,4,5]

    >>> a[::2]  # iterate over the whole list in 2-increments

    [1,3,5]

    The special case x[::-1] is a useful idiom for ‘x reversed’.

    >>> a[::-1]

    [5,4,3,2,1]

  • From 2.5 onwards dicts have a special method __missing__ that is invoked for missing items:

    >>> class
    MyDict(dict):

    …  def __missing__(self, key):

    …   self[key] = rv = []

    …   return rv


    >>> m = MyDict()

    >>> m["foo"].append(1)

    >>> m["foo"].append(2)

    >>> dict(m)

    {‘foo’: [1, 2]}

    There is also a dict subclass in collections called defaultdict that does pretty much the same but calls a function without arguments for not existing items:

    >>> from collections import defaultdict

    >>> m = defaultdict(list)

    >>> m["foo"].append(1)

    >>> m["foo"].append(2)

    >>> dict(m)

    {‘foo’: [1, 2]}

    I recommend converting such dicts to regular dicts before passing them to functions that don’t expect such subclasses. A lot of code uses d[a_key] and catches KeyErrors to check if an item exists which would add a new item to the dict.

  • Doctest: documentation and unit-testing at the same time.

    Example extracted fom python documentation:

    def factorial(n):

        “”"Return the factorial of n, an exact integer >= 0.

     
     

        If the result is small enough to fit in an int, return an int.

        Else return a long.

     
     

        >>> [factorial(n) for n in range(6)]

        [1, 1, 2, 6, 24, 120]

        >>> factorial(-1)

        Traceback (most recent call last):

            …

        ValueError: n must be >= 0

     
     

        Factorials of floats are OK, but the float must be an exact integer:

        “”"

     
     

        import math

        if
    not n >= 0:

            raise
    ValueError(“n must be >= 0″)

        if math.floor(n) != n:

            raise
    ValueError(“n must be exact integer”)

        if n+1 == n:  # catch a value like 1e300

            raise
    OverflowError(“n too large”)

        result = 1

        factor = 2

        while factor <= n:

            result *= factor

            factor += 1

        return result

     
     

    def _test():

        import doctest

        doctest.testmod()    

     
     

    if __name__ == “__main__”:

        _test()

  • Descriptors

    They’re the magic behind a whole bunch of core Python features.

    When you use dotted access to look up a member (eg, x.y), Python first looks for the member in the instance dictionary. If it’s not found, it looks for it in the class dictionary. If it finds it in the class dictionary, and the object implements the descriptor protocol, instead of just returning it, Python executes it. A descriptor is any class that implements the getset, or del methods.

    Here’s how you’d implement your own (read-only) version of property using descriptors:

    class
    Property(object):

        def __init__(self, fget):

            self.fget = fget

     
     

        def __get__(self, obj, type):

            if obj is
    None:

                return
    self

            return
    self.fget(obj)

    and you’d use it just like the built-in property():

    class
    MyClass(object):

        @Property

        def foo(self):

            return
    “Foo!”

    Descriptors are used in Python to implement properties, bound methods, static methods, class methods and slots, amongst other things. Understanding them makes it easy to see why a lot of things that previously looked like Python ‘quirks’ are the way they are.

    Raymond Hettinger has an excellent tutorial that does a much better job of describing them than I do.

  • Sending values into generator functions. For example having this function:

    def mygen():

      “”"Yield 5 until something else is passed back via send()”"”

      a = 5

      while
    True:

        f = yield(a) #yield a and possibly get f in return

        if f: a = f  #store the new value

    You can:

    >>> g = mygen()

    >>> g.next()

    5

    >>> g.next()

    5

    >>> g.send(7)  #we send this back to the generator

    7

    >>> g.next() #now it will yield 7 until we send something else

    7

  • One line Variable value swapping

    >>> a = 10

    >>> b = 5

    >>> a, b = b, a

     
     

    >>> print a

    5

    >>> print b

    10

    a will have the value of b and so on.

    This is a side effect of python packing and unpacking feature.

  • enumerate

    Wrap an iterable with enumerate and it will yield the item along with it’s index.

    For example:

    >>> a = ['a', 'b', 'c', 'd', 'e']

    >>> for index, item in enumerate(a): print index, item


    0 a

    1 b

    2 c

    3 d

    4 e

    >>>

  • Creating new types at runtime

    >>> NewType = type(“NewType”, (object,), {“x”: “hello”})

    >>> n = NewType()

    >>> n.x

    “hello”

    which is exactly the same as

    >>> class
    NewType(object):

    >>>     x = “hello”

    >>> n = NewType()

    >>> n.x

    “hello”

    Probably not the most useful thing, but nice to know.

    Edit: Fixed name of new type, should be NewType to be the exact same thing as with class statement.

     
     

    查看更多:http://stackoverflow.com/questions/101268/hidden-features-of-python

    这个页面里收集了很多python技巧

    Onenote不错,再试一下Onenote发帖,呵呵

     
     

Category: Python, linux  | Tags: , ,  | Leave a Comment
星期三, 10月 08th, 2008 | Author: Zealot

  • 获取Squid
  • 编译安装
  • 快速配置
  • 运行Squid
Category: linux  | Tags: , , ,  | Leave a Comment
星期三, 08月 06th, 2008 | Author: Zealot

这个命令用的比较多了,作用很简单:改变文件的权限

平时主要能涉及到的就读写执行三种权限了,分别对应rwx

主要形式用的比较多的就是:”chmod 三个数字表示权限 文件” 和 “chomd a+x 文件”,其中a表示所有用户,还有u,g,加好增加相应权限,减号相反。目录的执行权限定义不一样。

详细介绍如下:

http://blog.csdn.net/chenshaoying/archive/2008/08/04/2767064.aspx

chmod用于改变文件或目录的访问权限。用户用它控制文件或目录的访问权限。该命令有两种用法。一种是包含字母和操作符表达式的文字设定法;另一种是包含数字的数字设定法。

1. 文字设定法

语法:chmod [who] [+ | - | =] [mode] 文件名

命令中各选项的含义为:

操作对象who可是下述字母中的任一个或者它们的组合:
  u 表示“用户(user)”,即文件或目录的所有者。
  g 表示“同组(group)用户”,即与文件属主有相同组ID的所有用户。
  o 表示“其他(others)用户”。
  a 表示“所有(all)用户”。它是系统默认值。
操作符号可以是:
  + 添加某个权限。
  - 取消某个权限。
  = 赋予给定权限并取消其他所有权限(如果有的话)。
设置 mode 所表示的权限可用下述字母的任意组合:
  r 可读。
  w 可写。
   x 可执行。
  X 只有目标文件对某些用户是可执行的或该目标文件是目录时才追加x 属性。
  s 在文件执行时把进程的属主或组ID置为该文件的文件属主。
      方式“u+s”设置文件的用户ID位,“g+s”设置组ID位。
  t 保存程序的文本到交换设备上。
  u 与文件属主拥有一样的权限。
  g 与和文件属主同组的用户拥有一样的权限。
  o 与其他用户拥有一样的权限。
文件名:以空格分开的要改变权限的文件列表,支持通配符。

在一个命令行中可给出多个权限方式,其间用逗号隔开。例如:

chmod g+r,o+r example  % 使同组和其他用户对文件example 有读权限。

2. 数字设定法

我们必须首先了解用数字表示的属性的含义:0表示没有权限,1表示可执行权限, 2表示可写权限,4表示可读权限,然后将其相加。所以数字属性的格式应为3个从0到7的八进制数,其顺序是(u)(g)(o)。

例如,如果想让某个文件的属主有“读/写”二种权限,需要把4(可读)+2(可写)=6(读/写)。

数字设定法的一般形式为:

语法:chmod [mode] 文件名

指令实例:

chmod a+x sort
% 即设定文件sort的属性为:
 文件属主(u) 增加执行权限
 与文件属主同组用户(g) 增加执行权限
 其他用户(o) 增加执行权限

chmod ug+w,o-x text
% 即设定文件text的属性为:
 文件属主(u) 增加写权限
 与文件属主同组用户(g) 增加写权限
 其他用户(o) 删除执行权限

chmod u+s a.out
% 假设执行chmod后a.out的权限为(可以用ls – l a.out命令来看):
 –rws--x--x 1 inin users 7192 Nov 4 14:22 a.out
 并且这个执行文件要用到一个文本文件shiyan1.c,其文件存取权限为“–rw-------”,
  即该文件只有其属主具有读写权限。
   当其他用户执行a.out这个程序时,他的身份因这个程序暂时变成inin(由于chmod
  命令中使用了s选项),所以他就能够读取shiyan1.c这个文件(虽然这个文件被设定为
  其他人不具备任何权限),这就是s的功能。
  因此,在整个系统中特别是root本身,最好不要过多的设置这种类型的文件(除非
  必要)这样可以保障系统的安全,避免因为某些程序的bug而使系统遭到入侵。

chmod a–x mm.txt
chmod –x mm.txt
chmod ugo–x mm.txt
% 以上这三个命令都是将文件mm.txt的执行权限删除,它设定的对象为所有使用者。

$ chmod 644 mm.txt
% 即设定文件mm.txt的属性为:-rw-r--r--
 文件属主(u)inin 拥有读、写权限
 与文件属主同组人用户(g) 拥有读权限
 其他人(o) 拥有读权限

chmod 750 wch.txt
% 即设定wchtxt这个文件的属性为:-rwxr-x---
 文件主本人(u)inin 可读/可写/可执行权
 与文件主同组人(g) 可读/可执行权
 其他人(o) 没有任何权限
Category: linux  | Tags: , , ,  | Leave a Comment
星期三, 08月 06th, 2008 | Author: Zealot

想写很多东西,但一直不知道从那入手,转几篇再看看吧

sed之前用的不多,不太熟,关键时候没怎么敢乱用,主要用来批量替换很多文件吧

之前用过几次都是改很多文件中的东西,通过sed ’s/$1/$1/g’检查一下,没问题的话加上-i参数执行:)

http://www.oracle.com/technology/global/cn/pub/articles/dulaney_sed.html

Linux 系统管理员

使用 sed 编辑器
作者:Emmett Dulaney

sed 编辑器是 Linux 系统管理员的工具包中最有用的资产之一,
因此,有必要彻底地了解其应用

Linux 操作系统最大的一个好处是它带有各种各样的实用工具。存在如此之多不同的实用工具,几乎不可能知道并了解所有这些工具。可以简化关键情况下操作的一个实用工具是 sed。它是任何管理员的工具包中最强大的工具之一,并且可以证明它自己在关键情况下非常有价值。

sed 实用工具是一个“编辑器”,但它与其它大多数编辑器不同。除了不面向屏幕之外,它还是非交互式的。这意味着您必须将要对数据执行的命令插入到命令行或要处 理的脚本中。当显示它时,请忘记您在使用 Microsoft Word 或其它大多数编辑器时拥有的交互式编辑文件功能。sed 在一个文件(或文件集)中非交互式、并且不加询问地接收一系列的命令并执行它们。因而,它流经文本就如同水流经溪流一样,因而 sed 恰当地代表了流编辑器。 它可以用来将所有出现的 “Mr. Smyth” 修改为 “Mr. Smith”,或将 “tiger cub” 修改为 “wolf cub”。流编辑器非常适合于执行重复的编辑,这种重复编辑如果由人工完成将花费大量的时间。其参数可能和一次性使用一个简单的操作所需的参数一样有限, 或者和一个具有成千上万行要进行编辑修改的脚本文件一样复杂。sed 是 Linux 和 UNIX 工具箱中最有用的工具之一,且使用的参数非常少。

sed 的工作方式

sed 实用工具按顺序逐行将文件读入到内存中。然后,它执行为该行指定的所有操作,并在完成请求的修改之后将该行放回到内存中,以将其转储至终端。完成了这一行 上的所有操作之后,它读取文件的下一行,然后重复该过程直到它完成该文件。如同前面所提到的,默认输出是将每一行的内容输出到屏幕上。在这里,开始涉及到 两个重要的因素—首先,输出可以被重定向到另一文件中,以保存变化;第二,源文件(默认地)保持不被修改。sed 默认读取整个文件并对其中的每一行进行修改。不过,可以按需要将操作限制在指定的行上。

该实用工具的语法为:

sed [options] '{command}' [filename]

在这篇文章中,我们将浏览最常用的命令和选项,并演示它们如何工作,以及它们适于在何处使用。

替换命令

sed 实用工具以及其它任何类似的编辑器的最常用的命令之一是用一个值替换另一个值。用来实现这一目的的操作的命令部分语法是:

's/{old value}/{new value}/'

因而,下面演示了如何非常简单地将 “tiger” 修改为 “wolf”:

$ echo The tiger cubs will meet on Tuesday after school | sed
's/tiger/wolf/'
The wolf cubs will meet on Tuesday after school
$

注意如果输入是源自之前的命令输出,则不需要指定文件名—同样的原则也适用于 awk、sort 和其它大多数 Linux\UNIX 命令行实用工具程序。

多次修改

如果需要对同一文件或行作多次修改,可以有三种方法来实现它。第一种是使用 “-e” 选项,它通知程序使用了多条编辑命令。例如:

$ echo The tiger cubs will meet on Tuesday after school | sed -e '
s/tiger/wolf/' -e 's/after/before/'
The wolf cubs will meet on Tuesday before school
$

这是实现它的非常复杂的方法,因此 “-e” 选项不常被大范围使用。更好的方法是用分号来分隔命令:

$ echo The tiger cubs will meet on Tuesday after school | sed '
s/tiger/wolf/; s/after/before/'
The wolf cubs will meet on Tuesday before school
$

注意分号必须是紧跟斜线之后的下一个字符。如果两者之间有一个空格,操作将不能成功完成,并返回一条错误 消息。这两种方法都很好,但许多管理员更喜欢另一种方法。要注意的一个关键问题是,两个撇号 (’ ‘) 之间的全部内容都被解释为 sed 命令。直到您输入了第二个撇号,读入这些命令的 shell 程序才会认为您完成了输入。这意味着可以在多行上输入命令—同时 Linux 将提示符从 PS1 变为一个延续提示符(通常为 “>”)—直到输入了第二个撇号。一旦输入了第二个撇号,并且按下了 Enter 键,则处理就进行并产生相同的结果,如下所示:

$ echo The tiger cubs will meet on Tuesday after school | sed '
> s/tiger/wolf/
> s/after/before/'
The wolf cubs will meet on Tuesday before school
$

全局修改

让我们开始一次看似简单的编辑。假定在要修改的消息中出现了多次要修改的项目。默认方式下,结果可能和预期的有所不同,如下所示:

$ echo The tiger cubs will meet this Tuesday at the same time
as the meeting last Tuesday | sed 's/Tuesday/Thursday/'
The tiger cubs will meet this Thursday at the same time
as the meeting last Tuesday
$

与将出现的每个 “Tuesday” 修改为 “Thursday” 相反,sed 编辑器在找到一个要修改的项目并作了修改之后继续处理下一行,而不读整行。sed 命令功能大体上类似于替换命令,这意味着它们都处理每一行中出现的第一个选定序列。为了替换出现的每一个项目,在同一行中出现多个要替换的项目的情况下, 您必须指定在全局进行该操作:

$ echo The tiger cubs will meet this Tuesday at the same time
as the meeting last Tuesday | sed 's/Tuesday/Thursday/g'
The tiger cubs will meet this Thursday at the same time
as the meeting last Thursday
$

请记住不管您要查找的序列是否仅包含一个字符或词组,这种对全局化的要求都是必需的。

sed 还可以用来修改记录字段分隔符。例如,以下命令将把所有的 tab 修改为空格:

sed 's/	/ /g'

其中,第一组斜线之间的项目是一个 tab,而第二组斜线之间的项目是一个空格。作为一条通用的规则,sed 可以用来将任意的可打印字符修改为任意其它的可打印字符。如果您想将不可打印字符修改为可打印字符—例如,铃铛修改为单词 “bell”—sed 不是适于完成这项工作的工具(但 tr 是)。

有时,您不想修改在一个文件中出现的所有指定项目。有时,您只想在满足某些条件时才作修改—例如,在与其它一些数据匹配之后才作修改。为了说明这一点,请考虑以下文本文件:

$ cat sample_one
one     1
two     1
three   1
one     1
two     1
two     1
three   1
$

假定希望用 “2″ 来替换 “1″,但仅在单词 “two” 之后才作替换,而不是每一行的所有位置。通过指定在给出替换命令之前必须存在一次匹配,可以实现这一点:

$ sed '/two/ s/1/2/' sample_one
one     1
two     2
three   1
one     1
two     2
two     2
three   1
$

现在,使其更加准确:

$ sed '
> /two/ s/1/2/
> /three/ s/1/3/' sample_one
one     1
two     2
three   3
one     1
two     2
two     2
three   3
$

请再次记住唯一改变了的是显示。如果您查看源文件,您将发现它始终保持不变。您必须将输出保存至另一个文 件,以实现永久保存。值得重复的是,不对源文件作修改实际是祸中有福—它让您能够对文件进行试验而不会造成任何实际的损害,直到让正确命令以您预期和希望 的方式进行工作。

以下命令将修改后的输出保存至一个新的文件:

$ sed '
> /two/ s/1/2/
> /three/ s/1/3/' sample_one > sample_two

该输出文件将所有修改合并在其中,并且这些修改通常将在屏幕上显示。现在可以用 head、cat 或任意其它类似的实用工具来进行查看。

脚本文件

sed 工具允许您创建一个脚本文件,其中包含从该文件而不是在命令行进行处理的命令,并且 sed 工具通过 “-f” 选项来引用。通过创建一个脚本文件,您能够一次又一次地重复运行相同的操作,并指定比每次希望从命令行进行处理的操作详细得多的操作。

考虑以下脚本文件:

$ cat sedlist
/two/ s/1/2/
/three/ s/1/3/
$

现在可以在数据文件上使用脚本文件,获得和我们之前看到的相同的结果:

$ sed -f sedlist sample_one
one     1
two     2
three   3
one     1
two     2
two     2
three   3
$

注意当调用 “-f” 选项时,在源文件内或命令行中不使用撇号。脚本文件,也称为源文件,对于想重复多次的操作和从命令行运行可能出错的复杂命令很有价值。编辑源文件并修改一个字符比在命令行中重新输入一条多行的项目要容易得多。

限制行

编辑器默认查看输入到流编辑器中的每一行,且默认在输入到流编辑器中的每一行上进行编辑。这可以通过在发出命令之前指定约束条件来进行修改。例如,只在此示例文件的输出的第 5 和第 6 行中用 “2″ 来替换 “1″,命令将为:

$ sed '5,6 s/1/2/' sample_one
one     1
two     1
three   1
one     1
two     2
two     2
three   1
$

在这种情况下,因为要修改的行是专门指定的,所以不需要替换命令。因此,您可以灵活地根据匹配准则(可以是行号或一种匹配模式)来选择要修改哪些行(从根本上限制修改)。

禁止显示

sed 默认将来自源文件的每一行显示到屏幕上(或重定向到一个文件中),而无论该行是否受到编辑操作的影响,”-n” 参数覆盖了这一操作。”-n” 覆盖了所有的显示,并且不显示任何一行,而无论它们是否被编辑操作修改。例如:

$ sed -n -f sedlist sample_one
$

$ sed -n -f sedlist sample_one > sample_two
$ cat sample_two
$

在第一个示例中,屏幕上不显示任何东西。在第二个示例中,不修改任何东西,因此不将任何东西写到新的文件 中—它最后是空的。这不是否定了编辑的全部目的吗?为什么这是有用的?它是有用的仅因为 “-n” 选项能够被一条显示命令 (-p) 覆盖。为了说明这一点,假定现在像下面这样对脚本文件进行了修改:

$ cat sedlist
/two/ s/1/2/p
/three/ s/1/3/p
$

然后下面是运行它的结果:

$ sed -n -f sedlist sample_one
two     2
three   3
two     2
two     2
three   3
$

保持不变的行全部不被显示。只有受到编辑操作影响的行被显示了。在这种方式下,可以仅取出这些行,进行修改,然后把它们放到一个单独的文件中:

$ sed -n -f sedlist sample_one > sample_two
$

$ cat sample_two
two     2
three   3
two     2
two     2
three   3
$

利用它的另一种方法是只显示一定数量的行。例如,只显示 2-6 行,同时不做其它的编辑修改:

$ sed -n '2,6p' sample_one
two     1
three   1
one     1
two     1
two     1
$

其它所有的行被忽略,只有 2-6 行作为输出显示。这是一项出色的功能,其它任何工具都不能容易地实现。Head 将显示一个文件的顶部,而 tail 将显示一个文件的底部,但 sed 允许从任意位置取出想要的任意内容。

删除行

用一个值替换另一个值远非流编辑器可以执行的唯一功能。它还具有许多的潜在功能,在我看来第二种最常用的功能是删除。删除与替换的工作方式相同,只是它删除指定的行(如果您想要删除一个单词而不是一行,不要考虑删除,而应考虑用空的内容来替换它—s/cat//)。

该命令的语法是:

'{what to find} d'

从 sample_one 文件中删除包含 “two” 的所有行:

$ sed '/two/ d' sample_one
one     1
three   1
one     1
three   1
$

从显示屏中删除前三行,而不管它们的内容是什么:

$ sed '1,3 d' sample_one
one     1
two     1
two     1
three   1
$

只显示剩下的行,前三行不在显示屏中出现。对于流编辑器,一般当它们涉及到全局表达式时,特别是应用于删除操作时,有几点要记住:

  1. 上三角号 (^) 表示一行的开始,因此,如果 “two” 是该行的头三个字符,则
    sed '/^two/ d' sample_one

    将只删除该行。

  2. 美元符号 ($) 代表文件的结尾,或一行的结尾,因此,如果 “two” 是该行的最后三个字符,则
    sed '/two$/ d' sample_one

    将只删除该行。

将这两者结合在一起的结果:

sed '/^$/ d' {filename}

删除文件中的所有空白行。例如,以下命令将 “1″ 替换为 “2″,以及将 “1″ 替换为 “3″,并删除文件中所有尾随的空行:

$ sed '/two/ s/1/2/; /three/ s/1/3/; /^$/ d' sample_one
one     1
two     1
three   1
one     1
two     2
two     2
three   1
$

其通常的用途是删除一个标题。以下命令将删除文件中所有的行,从第一行直到第一个空行:

sed '1,/^$/ d' {filename}

添加和插入文本

可以结合使用 sed 和 “a” 选项将文本添加到一个文件的末尾。实现方法如下:

$ sed '$a\
> This is where we stop\
> the test' sample_one
one     1
two     1
three   1
one     1
two     1
two     1
three   1
This is where we stop
the test
$

在该命令中,美元符号 ($) 表示文本将被添加到文件的末尾。反斜线 (\) 是必需的,它表示将插入一个回车符。如果它们被遗漏了,则将导致一个错误,显示该命令是错乱的;在任何要输入回车的地方您必须使用反斜线。

要将这些行添加到第 4 和第 5 个位置而不是末尾,则命令变为:

$ sed '3a\
> This is where we stop\
> the test' sample_one
one     1
two     1
three   1
This is where we stop
the test
one     1
two     1
two     1
three   1
$

这将文本添加到第 3 行之后。和几乎所有的编辑器一样,您可以选择插入而不是添加(如果您希望这样的话)。这两者的区别是添加跟在指定的行之后,而插入从指定的行开始。当用插入来代替添加时,只需用 “i” 来代替 “a”,如下所示:

$ sed '3i\
> This is where we stop\
> the test' sample_one
one     1
two     1
This is where we stop
the test
three   1
one     1
two     1
two     1
three   1
$

新的文本出现在输出的中间位置,而处理通常在指定的操作执行以后继续进行。

读写文件

重定向输出的功能已经演示过了,但需要指出的是,在编辑命令运行期间可以同步地读入和写出文件。例如,执行替换,并将 1-3 行写到名称为 sample_three 的文件中:

$ sed '
> /two/ s/1/2/
> /three/ s/1/3/
> 1,3 w sample_three' sample_one
one     1
two     2
three   3
one     1
two     2
two     2
three   3
$

$ cat sample_three
one     1
two     2
three   3
$

由于为 w (write) 命令指定了 “1,3″,所以只有指定的行被写到了新文件中。无论被写的是哪些行,所有的行都在默认输出中显示。

修改命令

除了替换项目之外,还可以将行从一个值修改为另一个值。要记住的是,替换是对字符逐个进行,而修改功能与删除类似,它影响整行:

$ sed '/two/ c\
> We are no longer using two' sample_one
one     1
We are no longer using two
three   1
one     1
We are no longer using two
We are no longer using two
three   1
$

修改命令与替换的工作方式很相似,但在范围上要更大些—将一个项目完全替换为另一个项目,而无论字符内容 或上下文。夸张一点讲,当使用替换时,只有字符 “1″ 被字符 “2″ 替换,而当使用修改时,原来的整行将被修改。在两种情况下,要寻找的匹配条件都仅为 “two”。

修改全部但……

对于大多数 sed 命令,详细说明各种功能要进行何种修改。利用感叹号,可以在除指定位置之外的任何地方执行修改—与默认的操作完全相反。

例如,要删除包含单词 “two” 的所有行,操作为:

$ sed '/two/ d' sample_one
one     1
three   1
one     1
three   1
$

而要删除除包含单词 “two” 的行之外的所有行,则语法变为:

$ sed '/two/ !d' sample_one
two     1
two     1
two     1
$

如果您有一个文件包含一系列项目,并且想对文件中的每个项目执行一个操作,那么首先对那些项目进行一次智能扫描并考虑将要做什么是很重要的。为了使事情变得更简单,您可以将 sed 与任意迭代例程(for、while、until)结合来实现这一目的。

比如说,假定您有一个名为 “animals” 的文件,其中包含以下项目:

pig
horse
elephant
cow
dog
cat

您希望运行以下例程:

#mcd.ksh
for I in $*
do
echo Old McDonald had a $I
echo E-I, E-I-O
done

结果将为,每一行都显示在 “Old McDonald has a” 的末尾。虽然对于这些项目的大部分这是正确的,但对于 “elephant” 项目,它有语法错误,因为结果应当为 “an elephant” 而不是 “a elephant”。利用 sed,您可以在来自 shell 文件的输出中检查这种语法错误,并通过首先创建一个命令文件来即时地更正它们:

#sublist
/ a a/ s/ a / an /
/ a e/ s/ a / an /
/a i/ s / a / an /
/a o/ s/ a / an /
/a u/ s/ a / an /

然后执行以下过程:

$ sh mcd.ksh 'cat animals' | sed -f sublist

现在,在运行了 mcd 脚本之后,sed 将在输出中搜索单个字母 a (空格,”a”,空格)之后紧跟了一个元音的任意位置。如果这种位置存在,它将把该序列修改为空格,”an”,空格。这样就使问题更正后才显示在屏幕上, 并确保各处的编辑人员在晚上可以更容易地入睡。结果是:

Old McDonald had a pig
E-I, E-I-O
Old McDonald had a horse
E-I, E-I-O
Old McDonald had an elephant
E-I, E-I-O
Old McDonald had a cow
E-I, E-I-O
Old McDonald had a dog
E-I, E-I-O
Old McDonald had a cat
E-I, E-I-O

提前退出

sed 默认读取整个文件,并只在到达末尾时才停止。不过,您可以使用退出命令提前停止处理。只能指定一条退出命令,而处理将一直持续直到满足调用退出命令的条件。

例如,仅在文件的前五行上执行替换,然后退出:

$ sed '
> /two/ s/1/2/
> /three/ s/1/3/
> 5q' sample_one
one     1
two     2
three   3
one     1
two     2
$

在退出命令之前的项目可以是一个行号(如上所示),或者一条查找/匹配命令:

$ sed '
> /two/ s/1/2/
> /three/ s/1/3/
> /three/q' sample_one
one     1
two     2
three   3
$

您还可以使用退出命令来查看超过一定标准数目的行,并增加比 head 中的功能更强的功能。例如,head 命令允许您指定您想要查看一个文件的前多少行—默认数为 10,但可以使用从 1 到 99 的任意一个数字。如果您想查看一个文件的前 110 行,您用 head 不能实现这一目的,但用 sed 可以:

sed 110q filename

处理问题

当使用 sed 时,要记住的重要事项是它的工作方式。它的工作方式是:读入一行,在该行上执行它已知要执行的所有任务,然后继续处理下一行。每一行都受给定的每一个编辑命令的影响。

如果您的操作顺序没有十分彻底地考虑清楚,那么这可能会很麻烦。例如,假定您需要将所有的 “two” 项目修改为 “three”,然后将所有的 “three” 修改为 “four”:

$ sed '
> /two/ s/two/three/
> /three/ s/three/four/' sample_one
one     1
four     1
four   1
one     1
four     1
four     1
four   1
$

最初读取的 “two” 被修改为 “three”。然后它满足为下一次编辑建立的准则,从而变为 “four”。最终的结果不是想要的结果—现在除了 “four” 没有别的项目了,而本来应该有 “three” 和 “four”。

当执行这种操作时,您必须非常用心地注意指定操作的方式,并按某种顺序来安排它们,使得操作之间不会互相影响。例如:

$ sed '
> /three/ s/three/four/
> /two/ s/two/three/' sample_one
one     1
three     1
four   1
one     1
three     1
three     1
four   1
$

这非常有效,因为 “three” 值在 “two” 变成 “three” 之前得到修改。

标签和注释

可以在 sed 脚本文件中放置标签,这样一旦文件变得庞大,可以更容易地说明正在发生的事情。存在各种各样与这些标签相关的命令,它们包括:

  1. : 冒号表示一个标签名称。例如:
    :HERE

    以冒号开始的标签可以由 “b” 和 “t” 命令处理。

  2. b {label} 充当 “goto” 语句的作用,将处理发送至前面有一个冒号的标签。例如,
    b HERE

    将处理发送给行

    :HERE

    如果紧跟 b 之后没有指定任何标签,则处理转至脚本文件的末尾。

  3. t {label} 只要自上次输入行或执行一次 “t” 命令以来进行了替换操作,就转至该标签。和 “b” 一样,如果没有给定标签名,则处理转至脚本文件的末尾。
  4. # 符号作为一行的第一个字符将使整行被当作注释处理。注释行与标签不同,不能使用 b 或 t 命令来转到注释行上。
Category: linux  | Leave a Comment