免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: wingger
打印 上一主题 下一主题

[学习共享] shell基础二十篇 [复制链接]

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
21 [报告]
发表于 2004-11-28 22:26 |只看该作者

shell基础十二篇

替换!
让我们看一下 sed 最有用的命令之一,替换命令。使用该命令,可以将特定字符串或匹配的规则表达式用另一个字符串替换。下面是该命令最基本用法的示例:

  1. $ sed -e 's/foo/bar/' myfile.txt
复制代码

上面的命令将 myfile.txt 中每行第一次出现的 'foo'(如果有的话)用字符串 'bar' 替换,然后将该文件内容输出到标准输出。请注意,我说的是每行第一次出现,尽管这通常不是您想要的。在进行字符串替换时,通常想执行全局替换。也就是说,要替换每行中的所有出现,如下所示:

  1. $ sed -e 's/foo/bar/g' myfile.txt
复制代码

在最后一个斜杠之后附加的 'g' 选项告诉 sed 执行全局替换。

关于 's///' 替换命令,还有其它几件要了解的事。首先,它是一个命令,并且只是一个命令,在所有上例中都没有指定地址。这意味着,'s///' 还可以与地址一起使用来控制要将命令应用到哪些行,如下所示:

  1. $ sed -e '1,10s/enchantment/entrapment/g' myfile2.txt
复制代码


上例将导致用短语 'entrapment' 替换所有出现的短语 'enchantment',但是只在第一到第十行(包括这两行)上这样做。

  1. $ sed -e '/^$/,/^END/s/hills/mountains/g' myfile3.txt
复制代码

该例将用 'mountains' 替换 'hills',但是,只从空行开始,到以三个字符 'END' 开始的行结束(包括这两行)的文本块上这样做。

关于 's///' 命令的另一个妙处是 '/' 分隔符有许多替换选项。如果正在执行字符串替换,并且规则表达式或替换字符串中有许多斜杠,则可以通过在 's' 之后指定一个不同的字符来更改分隔符。例如,下例将把所有出现的 /usr/local 替换成 /usr:

  1. $ sed -e 's:/usr/local:/usr:g' mylist.txt
复制代码


在该例中,使用冒号作为分隔符。如果不指定分隔符,则变成了如下:
  1. $ sed -e 's/usr/local/usrg' mylist.txt
复制代码

这样就不能执行了
如果需要在规则表达式中指定分隔符字符,可以在它前面加入反斜杠。


规则表达式混乱
目前为止,我们只执行了简单的字符串替换。虽然这很方便,但是我们还可以匹配规则表达式。例如,以下 sed 命令将匹配从 '<' 开始、到 '>' 结束、并且在其中包含任意数量字符的短语。下例将删除该短语(用空字符串替换):

  1. $ sed -e 's/<.*>//g' myfile.html
复制代码


这是要从文件除去 HTML 标记的第一个很好的 sed 脚本尝试,但是由于规则表达式的特有规则,它不会很好地工作。原因何在?当 sed 试图在行中匹配规则表达式时,它要在行中查找最长的匹配。在我的前一篇 sed 文章中,这不成问题,因为我们使用的是 'd' 和 'p' 命令,这些命令总要删除或打印整行。但是,在使用 's///' 命令时,确实有很大不同,因为规则表达式匹配的整个部分将被目标字符串替换,或者,在本例中,被删除。这意味着,上例将把下行:

  1. <b>This</b> is what <b>I</b> meant.

  2. 变成:
  3. meant.
  4. 我们要的不是这个,而是:
  5. This is what I meant.
复制代码


幸运的是,有一种简便方法来纠正该问题。我们不输入“'<' 字符后面跟有一些字符并以 '>' 字符结束”的规则表达式,
而只需输入一个“'<' 字符,后面跟有任意数量非 '>' 字符,并以 '>' 字符结束”的规则表达式。这将与最短、而不是最长的可能性匹配。新命令如下:

  1. $ sed -e 's/<[^>]*>//g' myfile.html
复制代码


在上例中,'[^>]' 指定“非 '>'”字符,其后的 '*' 完成该表达式以表示“零或多个非 '>' 字符”。对几个 html 文件测试该命令,将它们管道输出 "more",然后仔细查看其结果。


更多字符匹配
'[ ]' 规则表达式语法还有一些附加选项。要指定字符范围,只要字符不在第一个或最后一个位置,就可以使用 '-',如下所示:

'[a-x]*'
这将匹配零或多个全部为 'a'、'b'、'c'...'v'、'w'、'x' 的字符。另外,可以使用 '[]' 字符类来匹配空格。以下是可用字符类的相当完整的列表:

字符类 描述
[] 字母数字 [a-z A-Z 0-9]
[] 字母 [a-z A-Z]
[] 空格或制表键
[] 任何控制字符
[] 数字 [0-9]
[] 任何可视字符(无空格)
[] 小写 [a-z]
[] 非控制字符
[] 标点字符
[] 空格
[] 大写 [A-Z]
[] 十六进制数字 [0-9 a-f A-F]


尽可能使用字符类是很有利的,因为它们可以更好地适应非英语 locale(包括某些必需的重音字符等等).


高级替换功能
我们已经看到如何执行简单甚至有些复杂的直接替换,但是 sed 还可以做更多的事。实际上可以引用匹配规则表达式的部分或全部,并使用这些部分来构造替换字符串。作为示例,假设您正在回复一条消息。下例将在每一行前面加上短语 "ralph said: ":

  1. $ sed -e 's/.*/ralph said: &/' origmsg.txt
复制代码


输出如下:
  1. ralph said: Hiya Jim, ralph said: ralph said:
  2. I sure like this sed stuff! ralph said:
复制代码


该例的替换字符串中使用了 '&' 字符,该字符告诉 sed 插入整个匹配的规则表达式。因此,可以将与 '.*' 匹配的任何内容(行中的零或多个字符的最大组或整行)插入到替换字符串中的任何位置,甚至多次插入。这非常好,但 sed 甚至更强大。


那些极好的带反斜杠的圆括号
's///' 命令甚至比 '&' 更好,它允许我们在规则表达式中定义区域,然后可以在替换字符串中引用这些特定区域。作为示例,假设有一个包含以下文本的文件:

  1. foo bar oni eeny meeny miny larry curly moe jimmy the weasel
复制代码


现在假设要编写一个 sed 脚本,该脚本将把 "eeny meeny miny" 替换成 "Victor eeny-meeny Von miny" 等等。要这样做,首先要编写一个由空格分隔并与三个字符串匹配的规则表达式。

  1. '.* .* .*'
复制代码


现在,将在其中每个感兴趣的区域两边插入带反斜杠的圆括号来定义区域:

  1. '\(.*\) \(.*\) \(.*\)'
复制代码


除了要定义三个可在替换字符串中引用的逻辑区域以外,该规则表达式的工作原理将与第一个规则表达式相同。下面是最终脚本:

  1. $ sed -e 's/\(.*\) \(.*\) \(.*\)/Victor \1-\2 Von \3/' myfile.txt
复制代码


如您所见,通过输入 '\x'(其中,x 是从 1 开始的区域号)来引用每个由圆括号定界的区域。输入如下:

  1. 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' 模式)。

  1. $ sed -n -e '=;p' myfile.txt
复制代码


无论什么时候指定了两个或更多命令,都按顺序将每个命令应用到文件的每一行。在上例中,首先将 '=' 命令应用到第 1 行,然后应用 'p' 命令。接着,sed 继续处理第 2 行,并重复该过程。虽然分号很方便,但是在某些场合下,它不能正常工作。另一种替换方法是使用两个 -e 选项来指定两个不同的命令:

  1. $ sed -n -e '=' -e 'p' myfile.txt
复制代码


然而,在使用更为复杂的附加和插入命令时,甚至多个 '-e' 选项也不能帮我们的忙。对于复杂的多行脚本,最好的方法是将命令放入一个单独的文件中。然后,用 -f 选项引用该脚本文件:

  1. $ sed -n -f mycommands.sed myfile.txt
复制代码


这种方法虽然可能不太方便,但总是管用。


一个地址的多个命令
有时,可能要指定应用到一个地址的多个命令。这在执行许多 's///' 以变换源文件中的字和语法时特别方便。要对一个地址执行多个命令,可在文件中输入 sed 命令,然后使用 '{ }' 字符将这些命令分组,如下所示:

  1. 1,20{         s/[Ll]inux/GNU\/Linux/g         s/samba/Samba/g         s/posix/POSIX/g }
复制代码


上例将把三个替换命令应用到第 1 行到第 20 行(包括这两行)。还可以使用规则表达式地址或者二者的组合:

  1. 1,/^END/{         s/[Ll]inux/GNU\/Linux/g         s/samba/Samba/g         s/posix/POSIX/g         p }
复制代码


该例将把 '{ }' 之间的所有命令应用到从第 1 行开始,到以字母 "END" 开始的行结束(如果在源文件中没发现 "END",则到文件结束)的所有行。


附加、插入和更改行
既然在单独的文件中编写 sed 脚本,我们可以利用附加、插入和更改行命令。这些命令将在当前行之后插入一行,在当前行之前插入一行,或者替换模式空间中的当前行。它们也可以用来将多行插入到输出。插入行命令用法如下:

  1. i\ This line will be inserted before each line
复制代码

如果不为该命令指定地址,那么它将应用到每一行,并产生如下的输出:

  1. This line will be inserted before each line line 1 here
  2. This line will be inserted before each line line 2 here
  3. This line will be inserted before each line line 3 here
  4. This line will be inserted before each line line 4 here
复制代码

如果要在当前行之前插入多行,可以通过在前一行之后附加一个反斜杠来添加附加行,如下所示:

  1. i\ insert this line\ and this one\ and this one\ and, uh, this one too.
复制代码

附加命令的用法与之类似,但是它将把一行或多行插入到模式空间中的当前行之后。其用法如下:

  1. a\ insert this line after each line.  Thanks! :)
复制代码

另一方面,“更改行”命令将实际替换模式空间中的当前行,其用法如下:

  1. c\ You're history, original line! Muhahaha!
复制代码

因为附加、插入和更改行命令需要在多行输入,所以将把它们输入到一个文本 sed 脚本中,然后通过使用 '-f' 选项告诉 sed 执行它们。使用其它方法将命令传递给 sed 会出现问题。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
22 [报告]
发表于 2004-11-28 22:26 |只看该作者

shell基础十二篇

文本转换
第一个实际脚本将 UNIX 风格的文本转换成 DOS/Windows 格式。您可能知道,基于 DOS/Windows 的文本文件在每一行末尾有一个 CR(回车)和 LF(换行),而 UNIX 文本只有一个换行。有时可能需要将某些 UNIX 文本移至 Windows 系统,该脚本将为您执行必需的格式转换。

$ sed -e 's/$/\r/' myunix.txt > mydos.txt



在该脚本中,'$' 规则表达式将与行的末尾匹配,而 '\r' 告诉 sed 在其之前插入一个回车。在换行之前插入回车,立即,每一行就以 CR/LF 结束。请注意,仅当使用 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



该脚本的工作原理很简单:替代规则表达式与一行的最末字符匹配,而该字符恰好就是回车。我们用空字符替换它,从而将其从输出中彻底删除。如果使用该脚本并注意到已经删除了输出中每行的最末字符,那么,您就指定了已经是 UNIX 格式的文本文件。也就没必要那样做了!

反转行
下面是另一个方便的小脚本。与大多数 Linux 发行版中包括的 "tac" 命令一样,该脚本将反转文件中行的次序。"tac" 这个名称可能会给人以误导,因为 "tac" 不反转行中字符的位置(左和右),而是反转文件中行的位置(上和下)。用 "tac" 处理以下文件:

foo bar oni



....将产生以下输出:

oni bar foo



可以用以下 sed 脚本达到相同目的:

$ sed -e '1!G;h;$!d' forward.txt > backward.txt



如果登录到恰巧没有 "tac" 命令的 FreeBSD 系统,将发现该 sed 脚本很有用。虽然方便,但最好还是知道该脚本为什么那样做。让我们对它进行讨论。

反转解释
首先,该脚本包含三个由分号隔开的单独 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/[[]]//g



第一个 '1d' 命令删除第一行,第二个命令从输出除去那些讨厌的 '^' 字符。最后一行除去文件中可能存在的任何控制字符。既然在处理外来文件格式,我想消除在中途遇到任何控制字符的风险。到目前为止,一切顺利。现在,要向该基本脚本中添加一些处理功能:

1d /^^/d s/[[]]//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/[[]]//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/[[]]//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

论坛徽章:
0
23 [报告]
发表于 2004-11-29 09:28 |只看该作者

shell基础十二篇

好东东。讲的深入浅出,对俺们这些初学者非常有帮助。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
24 [报告]
发表于 2004-11-29 10:01 |只看该作者

shell基础十二篇

原帖由 "tianci3982730" 发表:
肯定可以的无论在shell或在vi内都可
先按ctrl+v然后按ctrl+m
当你按ctrl+v后无任何显示
然后按ctrl+m就出现了^M了
按ctrl+v意思是接着输入控制字符的意思


可以了,呵,用ctrl+v再ctrl+M,但奇怪的事,我昨天会产生两个控制字符出来,可能键盘有问题。

我主要是命令行里用的字符^M不是用控制字符^M

论坛徽章:
0
25 [报告]
发表于 2004-11-29 14:11 |只看该作者

shell基础十二篇

感谢 收藏!

论坛徽章:
0
26 [报告]
发表于 2004-11-30 06:02 |只看该作者

shell基础十二篇

1,"如果只打印行号及匹配行,必须使用两个s e d命令,并使用e选项。第一个命令打印模式匹配行,第二个使用=选项打印行号,格式为sed -n -e /pattern/p -e /pattern/=
代码:
sed -n -e '/music/p' -e '/music/='  此条命令难以理解,-n和-e参数配合用时要注意些什么??

2,"整个文件都打印出来,并且匹配行打印了行号。如果只关心实际行号,使用- e选项。 "应该是-n参数~!
3,关于控制字符的输入我电脑上也通不过~!
望指正.

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
27 [报告]
发表于 2004-12-01 10:37 |只看该作者

shell基础十二篇

看完,对什么时候使用什么选项还是有些糊涂

man sed

  1. -n, --quiet, --silent
  2.                                                                                 
  3.               suppress automatic printing of pattern space

  4. 前面举过例子:
  5. [sam@Linux_chenwy sam]$ sed -n '2p' quote.txt
  6. It was an evening of splendid music and company.
  7. 如果没有-n,就把其它的都打印出来了
复制代码

                                                                                
  1. -e script, --expression=script

  2.               add the script to the commands to be executed

  3. 呵,跟多个表达式啊
  4. [sam@Linux_chenwy sam]$ sed -n -e '/music/p' -e '/music/='  quote.txt
  5. It was an evening of splendid music and company.
  6. 2
复制代码



  1. -f script-file, --file=script-file

  2.               add the contents of script-file to the commands to be executed
  3. 脚本文件
复制代码


  1.        -i[suffix], --in-place[=suffix]

  2.               edit files in place (makes backup if extension supplied)
  3. 寂寞烈火说过:是直接更更改原文件,不过最好用重定向
复制代码


       -l N, --line-length=N

              specify the desired line-wrap length for the `l' command


       -r, --regexp-extended

              use extended regular expressions in the script.

       -s, --separate

              consider  files  as  separate rather than as a single continuous
              long stream.


       -u, --unbuffered

              load minimal amounts of data from the input files and flush  the
              output buffers more often

       --help display this help and exit

       -V, --version
              output version information and exit

       If  no  -e, --expression, -f, or --file option is given, then the first
       non-option argument is taken as  the  sed  script  to  interpret.   All
       remaining  arguments  are  names  of input files; if no input files are
       specified, then the standard input is read.

       E-mail bug reports to: bonzini@gnu.org .  Be sure to include  the  word
       ``sed'' somewhere in the ``Subject:'' field.

论坛徽章:
0
28 [报告]
发表于 2004-12-01 16:46 |只看该作者

shell基础十二篇

要用sed把字符“\”转化成“'”该怎么写?
sed 's/\\/'/g' text不行,
sed 's/\\/\'/g' text也不行。
'不是特殊字符,但是sed语法规定的字符。

论坛徽章:
0
29 [报告]
发表于 2004-12-01 16:54 |只看该作者

shell基础十二篇

不能把'shell基础“这样的帖子整理一下,都置定吗?这个板块新贴速度太快。还是整理一下置定好。

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
30 [报告]
发表于 2004-12-01 16:57 |只看该作者

shell基础十二篇

echo 'a/b'|sed s#/#\'#
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP