关于便携式sed -e ... db或!??


12

编辑中, StéphaneChazelas通过 再次插入xpression break和另一个xpression语句来对我的格式进行POSIX 。现在,我想问问他为什么在评论中,但是答案已经是修订版18,并且几乎所有以前的版本都已经得到了类似免费赠品的感谢(如果您可以看到已删除的评论,您将会知道我的意思是)。另外,我认为我已经足够了解为什么用一种可能更有用的方式来表达这一点。所以在这里...sed-e-e

我通常会尽量将总sed -e表情数保持在一个,但我也更倾向于尽可能符合规范,尤其是当差异不超过a <space>和an时-e。但是,如果我不明白为什么应该这样做,我将无法做到这一点。以下是我所了解的当前状态的简要摘要:

  • ' -e '休息能够方便地站在了一个sed脚本\n在ewline突破sed命令行语句...... 我承认模糊为什么

  • sed {函数中}\n右括号必须在前面加一条斜线,如下所示:

    • <right-brace>前面应带有a,<newline>并且可以在<blank>字符之前或之后。
  • 一个\newline休息也同样需要进行以下任何使用...... abcirtw,或:

但是我不清楚{函数}定义与!not运算符之间的关系。我在规范中唯一提到否定运算符的地方是:

  • 一个功能之前可以有一个或多个!字符,在这种情况下,如果地址未选择模式空间,则应应用该功能。

这是否意味着使用a !表示{括号}$!命令是什么-它们是否也应被' -e '中断分隔?当Stéphane最近POSIX确定我的答案时,这是解决了什么问题?

我认为它要么是!否定运算符,要么是b他在编辑中处理的牧场语句(或者可能是同时出现),但我不知道,也不想。如果它是唯一b牧场语句,那么我相信一个d会在它的地方做,消除了需要' -e '休息,但我宁愿是一个hazarding前三次一定POSIXified答案。你能帮我吗?

毕竟我确实冒险了,但是没有很大的把握...


使用b;n;:b,您可以跳转到";n;:b"历史记录和POSIX sed中调用的标签(而GNU sed不在此范围内)。
斯特凡Chazelas

@StéphaneChazelas-我有责任- :你几个月前开车回家了。但是我不完全理解为什么第二个sed命令同样被POSIXified
mikeserv

1
在任何情况下,我的POSIX规范sed都是非常不清楚的。我过去曾要求澄清过几次,但我认为结果没有得到更新。一个很好的测试是尝试使用“传家宝”工具集(Solaris继承自原始版本,并且是POSIX规范的主要基础)。
斯特凡Chazelas

1
@syntaxerror-我完全不相信这种情况。如果您阅读了规范,s///就会发现ubstitution必须接受带有的链接。在必须用换行符分隔的命令周围,它变得模糊不清-e,在这种情况下该命令如何站立-至少对我有用。香港专业教育学院尚未偶然sed发现,虽然不能很好地解释它们。
mikeserv 2014年

1
@syntaxerror-我喜欢,但是您应该知道不需要;在换行符前使用-换行符就可以了。坦白地说,您可以完全不使用-e和,而只需像#!/bin/sed在换行符上的每个命令一样写一个文件-或不需要这样的定界符而不是用分隔的命令;。那那些需要换行通常是采取任意输入的- :这是指他们像标签名称和命令bt}花括号的功能,或rEAD和w仪式,其采取的文件名ARGS。他们全都需要跟随\n
mikeserv

Answers:


4

因此,这通常是一个问题的答案,尽管虽然我最终在一段时间前几乎每个情况下都能直观地弄清楚如何正确执行此操作,但直到最近我才设法通过标准中的文本相当具体地理解这一点。 。实际上,它的表达相当简单-我想我愚蠢地忽略了它很多次。

文本的相关部分均在标题下找到...

  • 在中编辑命令sed

    • 参数文本应由一行或多行组成。\n文本中每个嵌入的ewline之前应加\反斜杠。文本中的其他反斜杠应被删除,并且以下字符应按原义对待。

    • rw命令动词,并w标志提供给s命令,采取可选的RFile(或wfile)参数,从动词字母或标志的命令分离由一个或多个<blank>s; 实现可以允许零分隔作为扩展。

    • 命令谓词以外{abcirtw:,和#可以跟一个;分号,可选的<blank>s,和另一个命令动词。但是,当s命令动词与w标志一起使用时,以这种方式在其后跟另一个命令将产生未定义的结果。

...在...

  • 选项:可以选择多个-e-f选项。所有命令均应按照指定的顺序添加到脚本中,而不管其起源如何。

    • -e 脚本 -添加由指定的编辑命令脚本选项参数的结束脚本编辑命令。该脚本选项参数应具有相同的属性脚本操作,在上述OPERANDS部分。

    • -f script_file-将文件script_file中的编辑命令添加到脚本的末尾。

最后...

  • 操作数:

    • 脚本 -用作编辑命令脚本的字符串。该应用程序不应提供违反文本文件限制的脚本,除非最终字符不必是\n斜线。

因此,当您将其全部考虑在内时,有意义的是,任何可选的后跟任意参数且没有预定义定界符s d sub d repl d flag例如\n与之相反)的命令都应在未转义的ewline 处定界。

可以争论的是,s ; 预定义的定界符,但在这种情况下,将;for [aic]命令用于任何命令将需要在实现中包括专门用于这三个命令的单独的解析器- [:brw]例如,与用于的解析器分离。否则,实现将不得不要求在text参数中; 将反斜杠转义,并且从那以后只会变得越来越复杂。

如果写的sed是我希望既合规又高效的程序,那么我不会写这样一个单独的解析器-除非可能会[aic]产生语法错误(如果没有紧随其后的是\n斜线)。但这是一个简单的令牌化问题-结束定界符的情况通常是问题更大的情况。我只是这样写:

sed -e w\ file\\ -e one -e '...;and more commands'

...和...

sed -e a\\ -e appended\\ -e text -e '...;and more commands'

...的行为将非常相似,因为第一个将创建并写入一个名为:

file
one

...第二个将在输出的当前行上附加一个文本块,例如...

appended
text

...因为两者将共享相同的参数解析代码。

关于{ ... }and $!问题-好吧,我已经走了。带有地址的单个命令不是功能,而只是寻址的命令。除注释标签定义外,几乎所有命令(包括{ 函数定义) }都指定为接受/one//one/,/two/寻址。地址可以是行号或正则表达式,并且可以用取反。所以所有...#:!

$!d
/address/s/ub/stitution/
5!y/d/c/

...后面可以接一个;和更多根据标准的命令,但是如果单个地址需要更多命令,并且在执行每个命令后不应重新评估该地址,则应使用如下{功能}

/address/{ s//replace addressed pattern/
           s/do other conditional/substitutions/
           s/in the same context/without/
           s/reevaluating/address/
}

...在{同一行上不能跟一个结束符,}并且}除非在行的开头,否则不能发生一个结束符。但是,如果所包含的命令不应在其后跟随\newline,则它也不必在函数内。因此,上述所有s///障碍-甚至是右}括号,都可以随身携带;分号和其他命令。

我一直在谈论\newline分隔符,但-e我知道的问题是关于xpression语句的。但是两者实际上是相同的,并且关键的关系是,脚本可以是文字命令行参数,也可以是带有或的文件-[ef],并且两者都被解释为文本文件(指定为以a结尾\newline),但也需要实际结束\newline。这样,我可以合理地(我希望)推断出一个\0NUL定界的参数暗示着结尾的\newline,并且由于所有调用参数至少都得到一个\0NUL定界符,所以无论哪种都可以正常工作。

实际上,实际上,在任何情况下,除了标准指定了\反斜杠转义换行符的情况外,我都很好地发现了……

sed -e ... -e '...\' -e '...'

...工作也一样。而且,在每种情况下-在实践中- \n都应要求使用不漏电的大绳...

sed -e '...' -e '...'

...也为我工作。我上面提到的一个例外是...

sed -e 's/.../...\' -e '.../'

...这不适用于我的任何测试中的任何实现。我相当确定这可以归结为文本文件的要求以及分隔符s/// 附带的事实,因此没有理由使单个语句跨越\0NUL分隔的参数。

因此,总而言之,这是编写几种sed命令的可移植方法的简要介绍:

对于以下任何一项[aic]

...commands;[aic]\
text embedded newline\
delimiting newline
...more;commands...

...要么...

sed -e '...commands;[aic]\' -e 'text embedded newline\' -e 'delimiting newline' -e '.;.;.'

对于任何[:rwtb]地方的参数可选的 (为所有,但:,但分界\newline是不是。请注意,我从未有过一个理由去尝试多线标签参数将与被使用[:tb],但writing / reading在多行[RW]文件参数通常是毫无疑问的接受了sed这么久,我已经测试作为嵌入式\newline带\反斜杠转义。尽管如此,该标准仍未直接指定应将label[rw] file参数解析为与text相同参数,\n除了前两个定界线外,没有提及前两个定线。

...commands;[:trwb] parameter
...more;commands...

...要么...

sed -e '[:trwb] parameter' -e '...'

...其中<space>上述是可选的[:tb]

最后...

...;address[!]{ ...function;commands...
};...more;commands....

...要么...

sed -e '...;address[!]{ ...function;commands...' -e '};...more;commands...'

...其中任何上述命令(除外:也接受至少一个地址,并且可以是正则/表达式/或行号,并且可以与取反!,但是如果对一个地址的单个评估需要多个命令,则必须使用{函数上下文}定界括号。一个函数甚至可以包含多个以\n行分隔符分隔的命令,但是每个命令都必须在花括号内定界,否则会如此。

这就是编写可移植sed脚本的方法。


2
您为什么不接受自己的答案?
Philippos
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.