配色: 字号:
shell之sed命令全解.doc
2020-04-28 | 阅:  转:  |  分享 
  
shell之sed命令全解

请注意新的''-n''选项,该选项告诉sed除非明确要求打印模式空间,否则不这样做。您还会注意到,我们用''p''命令替换了''d''命令,如您所猜想的那样,这明确要求sed打印模式空间。就这样,将只打印匹配部分。有关地址的更多内容目前为止,我们已经看到了行地址、行范围地址和regexp地址。但是,还有更多的可能。我们可以指定两个用逗号分开的规则表达式,sed将与所有从匹配第一个规则表达式的第一行开始,到匹配第二个规则表达式的行结束(包括该行)的所有行匹配。例如,以下命令将打印从包含"BEGIN"的行开始,并且以包含"END"的行结束的文本块:$sed-n-e''/BEGIN/,/END/p''/my/test/file|more如果没发现"BEGIN",那么将不打印数据。如果发现了"BEGIN",但是在这之后的所有行中都没发现"END",那么将打印所有后续行。发生这种情况是因为sed面向流的特性--它不知道是否会出现"END"。C源代码示例如果只要打印C源文件中的main()函数,可输入:$sed-n-e''/main[[:space:]](/,/^}/p''sourcefile.c|more该命令有两个规则表达式''/main[[:space:]](/''和''/^}/'',以及一个命令''p''。第一个规则表达式将与后面依次跟有任意数量的空格或制表键以及开始圆括号的字符串"main"匹配。这应该与一般ANSICmain()声明的开始匹配。在这个特别的规则表达式中,出现了''[[:space:]]''字符类。这只是一个特殊的关键字,它告诉sed与TAB或空格匹配。如果愿意的话,可以不输入''[[:space:]]'',而输入''['',然后是空格字母,然后是-V,然后再输入制表键字母和'']''--Control-V告诉bash要插入“真正”的制表键,而不是执行命令扩展。使用''[[:space:]]''命令类(特别是在脚本中)会更清楚。好,现在看一下第二个regexp。''/^}''将与任何出现在新行行首的''}''字符匹配。如果代码的格式很好,那么这将与main()函数的结束花括号匹配。如果格式不好,则不会正确匹配--这是执行模式匹配任务的一件棘手之事。因为是处于''-n''安静方式,所以''p''命令还是完成其惯有任务,即明确告诉sed打印该行。试着对C源文件运行该命令--它应该输出整个main(){}块,包括开始的"main()"和结束的''}''。下一篇既然已经触及了基本知识,我们将在后两篇文章中加快步伐。如果想看一些更丰富的sed资料,请耐心一些--马上就有!同时,您可能想查看下列sed和规则表达式资源。sed是十分强大和小巧的文本流编辑器。在本文章系列的第二篇中,DanielRobbins为您演示如何使用sed来执行字符串替换、创建更大的sed脚本以及如何使用sed的附加、插入和更改行命令。sed是很有用(但常被遗忘)的UNIX流编辑器。在以批处理方式编辑文件或以有效方式创建shell脚本来修改现有文件方面,它是十分理想的工具。本文是前一篇介绍sed文章的续篇。替换!让我们看一下sed最有用的命令之一,替换命令。使用该命令,可以将特定字符串或匹配的规则表达式用另一个字符串替换。下面是该命令最基本用法的示例:$sed-e''s/foo/bar/''myfile.txt上面的命令将myfile.txt中每行第一次出现的''foo''(如果有的话)用字符串''bar''替换,然后将该文件内容输出到标准输出。请注意,我说的是每行第一次出现,尽管这通常不是您想要的。在进行字符串替换时,通常想执行全局替换。也就是说,要替换每行中的所有出现,如下所示:$sed-e''s/foo/bar/g''myfile.txt在最后一个斜杠之后附加的''g''选项告诉sed执行全局替换。关于''s///''替换命令,还有其它几件要了解的事。首先,它是一个命令,并且只是一个命令,在所有上例中都没有指定地址。这意味着,''s///''还可以与地址一起使用来控制要将命令应用到哪些行,如下所示:$sed-e''1,10s/enchantment/entrapment/g''myfile2.txt上例将导致用短语''entrapment''替换所有出现的短语''enchantment'',但是只在第一到第十行(包括这两行)上这样做。$sed-e''/^$/,/^END/s/hills/mountains/g''myfile3.txt该例将用''mountains''替换''hills'',但是,只从空行开始,到以三个字符''END''开始的行结束(包括这两行)的文本块上这样做。关于''s///''命令的另一个妙处是''/''分隔符有许多替换选项。如果正在执行字符串替换,并且规则表达式或替换字符串中有许多斜杠,则可以通过在''s''之后指定一个不同的字符来更改分隔符。例如,下例将把所有出现的/usr/local替换成/usr:$sed-e''s:/usr/local:/usr:g''mylist.txt在该例中,使用冒号作为分隔符。如果需要在规则表达式中指定分隔符字符,可以在它前面加入反斜杠。规则表达式混乱目前为止,我们只执行了简单的字符串替换。虽然这很方便,但是我们还可以匹配规则表达式。例如,以下sed命令将匹配从''<''开始、到''>''结束、并且在其中包含任意数量字符的短语。下例将删除该短语(用空字符串替换):$sed-e''s/<.>//g''myfile.html这是要从文件除去HTML标记的第一个很好的sed脚本尝试,但是由于规则表达式的特有规则,它不会很好地工作。原因何在?当sed试图在行中匹配规则表达式时,它要在行中查找最长的匹配。在我的前一篇sed文章中,这不成问题,因为我们使用的是''d''和''p''命令,这些命令总要删除或打印整行。但是,在使用''s///''命令时,确实有很大不同,因为规则表达式匹配的整个部分将被目标字符串替换,或者,在本例中,被删除。这意味着,上例将把下行:ThisiswhatImeant.变成:meant.我们要的不是这个,而是:ThisiswhatImeant.幸运的是,有一种简便方法来纠正该问题。我们不输入“''<''字符后面跟有一些字符并以''>''字符结束”的规则表达式,而只需输入一个“''<''字符后面跟有任意数量非''>''字符并以''>''字符结束”的规则表达式。这将与最短、而不是最长的可能性匹配。新命令如下:$sed-e''s/<[^>]>//g''myfile.html在上例中,''[^>]''指定“非''>''”字符,其后的''''完成该表达式以表示“零或多个非''>''字符”。对几个html文件测试该命令,将它们管道输出到"more",然后仔细查看其结果。更多字符匹配''[]''规则表达式语法还有一些附加选项。要指定字符范围,只要字符不在第一个或最后一个位置,就可以使用''-'',如下所示:''[a-x]''这将匹配零或多个全部为''a''、''b''、''c''...''v''、''w''、''x''的字符。另外,可以使用''[:space:]''字符类来匹配空格。以下是可用字符类的相当完整的列表:字符类描述[:alnum:]字母数字[a-zA-Z0-9][:alpha:]字母[a-zA-Z][:blank:]空格或制表键[:cntrl:]任何控制字符[:digit:]数字[0-9][:graph:]任何可视字符(无空格)[:lower:]小写[a-z][:print:]非控制字符[:punct:]标点字符[:space:]空格[:upper:]大写[A-Z][:xdigit:]十六进制数字[0-9a-fA-F]尽可能使用字符类是很有利的,因为它们可以更好地适应非英语locale(包括某些必需的重音字符等等).高级替换功能我们已经看到如何执行简单甚至有些复杂的直接替换,但是sed还可以做更多的事。实际上可以引用匹配规则表达式的部分或全部,并使用这些部分来构造替换字符串。作为示例,假设您正在回复一条消息。下例将在每一行前面加上短语"ralphsaid:":$sed-e''s/./ralphsaid:&/''origmsg.txt输出如下:ralphsaid:HiyaJim,ralphsaid:ralphsaid:Isurelikethissedstuff!ralphsaid:该例的替换字符串中使用了''&''字符,该字符告诉sed插入整个匹配的规则表达式。因此,可以将与''.''匹配的任何内容(行中的零或多个字符的最大组或整行)插入到替换字符串中的任何位置,甚至多次插入。这非常好,但sed甚至更强大。那些极好的带反斜杠的圆括号''s///''命令甚至比''&''更好,它允许我们在规则表达式中定义区域,然后可以在替换字符串中引用这些特定区域。作为示例,假设有一个包含以下文本的文件:foobaronieenymeenyminylarrycurlymoejimmytheweasel现在假设要编写一个sed脚本,该脚本将把"eenymeenyminy"替换成"Victoreeny-meenyVonminy"等等。要这样做,首先要编写一个由空格分隔并与三个字符串匹配的规则表达式。''...''现在,将在其中每个感兴趣的区域两边插入带反斜杠的圆括号来定义区域:''(.)(.)(.)''除了要定义三个可在替换字符串中引用的逻辑区域以外,该规则表达式的工作原理将与第一个规则表达式相同。下面是最终脚本:$sed-e''s/(.)(.)(.)/Victor1-2Von3/''myfile.txt如您所见,通过输入''x''(其中,x是从1开始的区域号)来引用每个由圆括号定界的区域。输入如下:Victorfoo-barVononiVictoreeny-meenyVonminyVictorlarry-curlyVonmoeVictorjimmy-theVonweasel随着对sed越来越熟悉,您可以花最小力气来进行相当强大的文本处理。您可能想如何使用熟悉的脚本语言来处理这种问题--能用一行代码轻易实现这样的解决方案吗?组合使用在开始创建更复杂的sed脚本时,需要有输入多个命令的能力。有几种方法这样做。首先,可以在命令之间使用分号。例如,以下命令系列使用''=''命令和''p''命令,''=''命令告诉sed打印行号,''p''命令明确告诉sed打印该行(因为处于''-n''模式)。$sed-n-e''=;p''myfile.txt无论什么时候指定了两个或更多命令,都按顺序将每个命令应用到文件的每一行。在上例中,首先将''=''命令应用到第1行,然后应用''p''命令。接着,sed继续处理第2行,并重复该过程。虽然分号很方便,但是在某些场合下,它不能正常工作。另一种替换方法是使用两个-e选项来指定两个不同的命令:$sed-n-e''=''-e''p''myfile.txt然而,在使用更为复杂的附加和插入命令时,甚至多个''-e''选项也不能帮我们的忙。对于复杂的多行脚本,最好的方法是将命令放入一个单独的文件中。然后,用-f选项引用该脚本文件:$sed-n-fmycommands.sedmyfile.txt这种方法虽然可能不太方便,但总是管用。一个地址的多个命令有时,可能要指定应用到一个地址的多个命令。这在执行许多''s///''以变换源文件中的字和语法时特别方便。要对一个地址执行多个命令,可在文件中输入sed命令,然后使用''{}''字符将这些命令分组,如下所示:1,20{s/[Ll]inux/GNU/Linux/gs/samba/Samba/gs/posix/POSIX/g}上例将把三个替换命令应用到第1行到第20行(包括这两行)。还可以使用规则表达式地址或者二者的组合:1,/^END/{s/[Ll]inux/GNU/Linux/gs/samba/Samba/gs/posix/POSIX/gp}该例将把''{}''之间的所有命令应用到从第1行开始,到以字母"END"开始的行结束(如果在源文件中没发现"END",则到文件结束)的所有行。附加、插入和更改行既然在单独的文件中编写sed脚本,我们可以利用附加、插入和更改行命令。这些命令将在当前行之后插入一行,在当前行之前插入一行,或者替换模式空间中的当前行。它们也可以用来将多行插入到输出。插入行命令用法如下:iThislinewillbeinsertedbeforeeachline如果不为该命令指定地址,那么它将应用到每一行,并产生如下的输出:Thislinewillbeinsertedbeforeeachlineline1hereThislinewillbeinsertedbeforeeachlineline2hereThislinewillbeinsertedbeforeeachlineline3hereThislinewillbeinsertedbeforeeachlineline4here如果要在当前行之前插入多行,可以通过在前一行之后附加一个反斜杠来添加附加行,如下所示:iinsertthislineandthisoneandthisoneand,uh,thisonetoo.附加命令的用法与之类似,但是它将把一行或多行插入到模式空间中的当前行之后。其用法如下:ainsertthislineaftereachline.Thanks!:)另一方面,“更改行”命令将实际替换模式空间中的当前行,其用法如下:cYou''rehistory,originalline!Muhahaha!因为附加、插入和更改行命令需要在多行输入,所以将把它们输入到一个文本sed脚本中,然后通过使用''-f''选项告诉sed执行它们。使用其它方法将命令传递给sed会出现问题。下一篇在下一篇、也是本sed系列的最后一篇文章中,我将为您演示许多使用sed来完成不同类型任务的极佳实例。我将不仅为您显示脚本做些什么,还显示为什么那样做。完成之后,您将掌握更多有关如何在不同项目中使用sed的极佳知识。到时候见!在这篇sed系列的总结性文章中,DanielRobbins带您体验sed的真正力量。在介绍完几个重要的sed脚本之后,他将通过将一个Quicken.QIF文件转换成可读文本格式来演示一些基本sed脚本的编写。该转换脚本不仅实用,而且还是展现sed脚本编写能力的极佳示例。强健的sed在第二篇sed文章中,我提供了一些示例来演示sed的工作原理,但是它们当中很少有示例能实际做特别有用的事。在这篇sed系列的最后文章中,我要改变那种方式,并使用sed来做实际的事。我将为您显示几个示例,它们不仅演示sed的能力,而且还做一些真正巧妙(和方便)的事。例如,在本文的后半部,将为您演示如何设计一个sed脚本来将.QIF文件从Intuit的Quicken金融程序转换成具有良好格式的文本文件。在那样做之前,我们将看一下不怎么复杂但却很有用的sed脚本。文本转换第一个实际脚本将UNIX风格的文本转换成DOS/Windows格式。您可能知道,基于DOS/Windows的文本文件在每一行末尾有一个CR(回车)和LF(换行),而UNIX文本只有一个换行。有时可能需要将某些UNIX文本移至Windows系统,该脚本将为您执行必需的格式转换。$sed-e''s/$//''myunix.txt>mydos.txt在该脚本中,''$''规则表达式将与行的末尾匹配,而''''告诉sed在其之前插入一个回车。在换行之前插入回车,立即,每一行就以CR/LF结束。请注意,仅当使用GNUsed3.02.80或以后的版本时,才会用CR替换''''。如果还没有安装GNUsed3.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"处理以下文件:foobaroni....将产生以下输出:onibarfoo可以用以下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")附加到模式空间("bar"),使模式空间的内容为"barfoo"。''h''命令将该内容放回保留空间保护起来,然后,''d''从模式空间删除该行,以便不打印它。对于最后的"oni"行,除了不删除模式空间的内容(由于''d''之前的''$!'')以及将模式空间的内容(三行)打印到标准输出之外,重复同样的步骤。现在,要用sed执行一些强大的数据转换。sedQIF魔法过去几个星期,我一直想买一份Quicken来结算我的银行帐户。Quicken是一个非常好的金融程序,当然会成功地完成这项工作。但是,经过考虑之后,我觉得自己可以轻易编写某个软件来结算我的支票簿。我想,毕竟,我是个软件开发人员!我开发了一个很好的小型支票簿结算程序(使用awk),它通过分析包含我的所有交易的文本文件的语法来计算余额。略微调整之后,我将其改进,以便可以象Quicken那样跟踪不同的贷款和借款类别。但是,我还要添加一个特性。最近,我将帐户转移到一家有联机Web帐户界面的银行。有一天,我注意到,这家银行的Web站点允许以Quicken的.QIF格式下载我的帐户信息。我马上觉得,如果可以将该信息转换成文本格式,那就太棒了。两种格式的故事在查看QIF格式之前,先看一下我的checkbook.txt格式:28Aug2000food--YSupermarket30.9425Aug2000watr-103YCheck10352.86在我的文件中,所有字段都由一个或多个制表符分开,每个交易占据一行。日期之后的下一个字段列出支出类型(如果是收入项,则为"-")。第三个字段列出收入类型(如果是支出项,则为"-")。然后,是一个支票号字段(如果为空,则还是"-"),一个交易完成字段("Y"或"N"),一个注释和一个美元金额字段。现在,让我们看一下QIF格式。当用文本查看器查看下载的QIF文件时,它看起来如下:!Type:BankD08/28/2000T-8.15NPCHECKCARDSUPERMARKET^D08/28/2000T-8.25NPCHECKCARDPUNJABRESTAURANT^D08/28/2000T-17.17NPCHECKCARDSUPERMARKET浏览过文件之后,不难猜出其格式--忽略第一行,其余的格式如下:D<数据>T<交易量>N<支票号>P<描述>^(这是字段分隔符)开始处理在处理象这样重要的sed项目时,不要气馁--sed允许您将数据逐渐修改成最终形式。在进行当中,可以继续细化sed脚本,直到输出与预期的完全一样为止。无需在试第一次时就保证其完全正确。要开始,首先创建一个名为"qiftrans.sed"的文件,然后开始修改数据:1d/^^/ds/[[:cntrl:]]//g第一个''1d''命令删除第一行,第二个命令从输出除去那些讨厌的''^''字符。最后一行除去文件中可能存在的任何控制字符。既然在处理外来文件格式,我想消除在中途遇到任何控制字符的风险。到目前为止,一切顺利。现在,要向该基本脚本中添加一些处理功能:1d/^^/ds/[[:cntrl:]]//g/^D/{s/^D(.)/1OUTYINNY/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:^(.)/(.)/(.):213:}首先,添加一个''/^D/''地址,以便sed只在遇到QIF数据字段的第一个字符''D''时才开始处理。当sed将这样一行读入其模式空间时,将按顺序执行花括号中的所有命令。花括号中的第一个命令将把如下行:D08/28/2000变换成:08/28/2000OUTYINNY当然,现在的格式还不完美,但没关系。我们将在进行过程中逐渐细化模式空间的内容。后面12行的最后效果是将数据变换成三个字母的格式,最后一行从数据中除去三个斜杠。最后得到这一行:Aug282000OUTYINNYOUTY和INNY字段是占位符,以后将被替换。现在还不能确定它们,因为如果美元金额为负,将把OUTY和INNY设置成"misc"和"-",但是,如果美元金额为正,将分别把它们更改成"-"和"inco"。既然还没有读入美元金额,所以,需要暂时使用占位符。细化现在进一步细化:1d/^^/ds/[[:cntrl:]]//g/^D/{s/^D(.)/1OUTYINNY/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:^(.)/(.)/(.):213:NNNs/T(.)N(.)P(.)/NUM2NUMY3AMT1AMT/s/NUMNUM/-/s/NUM([0-9])NUM/1/s/([0-9]),/1/}后七行有些复杂,所以将详细讨论它们。首先,连续使用三个''N''命令。''N''命令告诉sed将下一行读入输入中,然后将其附加到当前模式空间。这三个''N''命令导致将下三行附加到当前模式空间缓冲区,现在这一行看起来如下:28Aug2000OUTYINNYT-8.15NPCHECKCARDSUPERMARKETsed的模式空间变得很难看--需要除去额外的新行,并执行某些附加的格式化。要这样做,将使用替代命令。要匹配的模式为:''T.N.P.''这将与后面依次跟有''T''、零或多个字符、新行、''N''、任何数量的字符、新行、''P''、以及任何数量字符的新行匹配。呀!这个规则表达式将与刚刚附加到模式空间的三行的全部内容匹配。但我们要重新格式化该区域,而不是整个替换它。美元金额、支票号(如果有的话)和描述需要出现在替换字符串中。要这样做,我们用带有反斜杠的圆括号括起那些“感兴趣部分”,以便可以在替换字符串中引用它们(使用''1''、''2和''3''来告诉sed将它们插入到何处)。以下是最后的命令:s/T(.)N(.)P(.)/NUM2NUMY3AMT1AMT/该命令将我们的行变换成:28Aug2000OUTYINNYNUMNUMYCHECKCARDSUPERMARKETAMT-8.15AMT虽然该行正变得好一些,但是,有几件事一看就有点...啊...有趣。首先是那个愚蠢的"NUMNUM"字符串--其目的何在?如果查看sed脚本的后两行,就会发现其目的,后两行将把"NUMNUM"替换成"-",而把"NUM""NUM"替换成。如您所见,用愚蠢的标记括起支票号允许我们在该字段为空时方便地插入一个"-"。结束尝试最后一行除去数字后的逗号。它把如"3,231.00"这样的美元金额转换成我使用的格式"3231.00"。现在,让我们看一下最终脚本:最终的“QIF到文本”脚本1d/^^/ds/[[:cntrl:]]//g/^D/{s/^D(.)/1OUTYINNY/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:^(.)/(.)/(.):213:NNNs/T(.)N(.)P(.)/NUM2NUMY3AMT1AMT/s/NUMNUM/-/s/NUM([0-9])NUM/1/s/([0-9]),/1//AMT-[0-9].[0-9]AMT/bfixnegss/AMT(.)AMT/1/s/OUTY/-/s/INNY/inco/bdone:fixnegss/AMT-(.)AMT/1/s/OUTY/misc/s/INNY/-/:done}附加的十一行使用替代和一些分支功能来美化输出。首先看一下这行:/AMT-[0-9].[0-9]AMT/bfixnegs该行包含一个格式为"/regexp/blabel"的分支命令。如果模式空间与规则表达式匹配,sed将分支到fixnegs标号。您应该可以轻易找到该标号,它在代码中为":fixnegs"。如果规则表达式不匹配,则以常规方式继续处理下一个命令。既然您理解该命令本身的工作原理,让我们看一下分支。如果看一下分支规则表达式,将看到它与后面依次跟有''-''、任意数量的数字、一个''.''、任意数量的数字和''AMT''的字符串''AMT''匹配。就象我确信您已猜到一样,该规则表达式专门处理负的美元金额。在这之前,用''ATM''括起美元金额,以便以后可以轻易找到它。因为规则表达式只与以''-''开始的美元金额匹配,所以,该分支只在恰巧处理借款时才发生。如果正处理贷款,应该将OUTY设置成''misc'',将INNY设置成''-'',并且应该除去贷款数量前面的负号。如果跟踪代码的流程,将看到实际情况正是这样。如果不执行分支,则用''-''替换OUTY,用''inco''替换INNY。完成了!现在输出行是完美的:28Aug2000misc--YCHECKCARDSUPERMARKET-8.15别犯糊涂如您所见,只要循序渐进地解决问题,使用sed转换数据就没有那么难。不要试图使用一个sed命令或一下子解决所有问题。相反,要朝着目标逐步进行,并不断改进sed脚本,直到其输出正如您希望那样为止。sed有许多功能,希望您已非常熟悉其内部工作原理并继续努力以进一步掌握它!



献花(0)
+1
(本文系AiChemi首藏)