为了账号安全,请及时绑定邮箱和手机立即绑定

SED没有给我正确的Mac换行操作-GNU sed和BSD/OSX sed之间的差异

/ 猿问

SED没有给我正确的Mac换行操作-GNU sed和BSD/OSX sed之间的差异

慕村225694 2019-07-03 17:33:01

SED没有给我正确的Mac换行操作-GNU sed和BSD/OSX sed之间的差异

我用的是这个参考资料:SED帮助:匹配和替换文字“\n”(不是换行符)

我有一个文件“test1.txt”,其中包含一个字符串hello\n

我使用这个命令搜索并用实际的新行字符替换“\n”:

sed -i '' 's/\\n/\n/g' test1.txt

但结果是:地狱再见..它只是将“\n”替换为“n”,而不是实际的新行。这与/t一样,它将留下一个“t”而不是一个选项卡。

“表示MAC中未定义的错误:http:/mpecherty.wordpress.com/2010/05/27/Diff-with-sed-就地编辑-onmac-os-x-vs-linux/

更新:

我尝试了@hek2mgl建议的两个命令:

sed -i 's/\\n/\n/g' test.txt
# Or:
sed -i'' 's/\\n/\n/g' test.txt

虽然它们可能与Linux一起工作,但在MAC操作系统下,我得到了以下错误:

sed: 1: "test1.txt": undefined label 'est1.txt'

不知道为什么我不能让这件事起作用。提前谢谢。


查看完整描述

2 回答

?
月关宝盒

与BSD/MacOSsed中使用换行符替换串一种s函数调用时,必须使用\-逃跑实际纽林-逃逸顺序\n支持(不像在雷吉电话的一部分)。

  • 任一*只需插入实际Newline:

    sed -i '' 's/\\n/\
    /g' test1.txt
  • *使用Ansi C-引号字符串($'...')插入换行符($'\n';在bashksh,或zsh):

    sed -i '' 's/\\n/\'$'\n''/g' test1.txt

GNU sed相反,是吗?识别\n在替换字符串中;详细了解这两种实现之间的差异。


GNU之间的差异sed(Linux)和BSD/MacOSsed

MacOS使用BSD版本sed[1],它在许多方面与GNU sed随附的版本linux发行版。

他(她,它)们的公分母是由POSIX*见POSIXsed规格。

这个最便携方法是为了仅使用POSIX功能,然而,限制功能:

  • 特别要注意的是,POSIX指定

    只支持基本正则表达式

    ,有许多限制(例如,不支持

    |

    (交替)根本没有直接支持

    +

    ?

    )和不同的逃逸要求。
    • 警告:

      GNUsed(没有-r), 是吗?支撑\|\+\?,不符合POSIX的;使用--posix禁用

      (见下文)。
  • 仅使用POSIX功能:

    • 控制字符序列,如

      \n

      \t

      一般不支持。
    • 标签和分支命令(例如,

      b

      后面跟着一个

      实际

      通过单独的新行或续行

      -e

      选择。
    • 详情见下文。
    • (两个版本):使用

      这个

      -n

      -e

      选项(特别是不要使用

      -E

      -r

      打开对.的支持

      扩展

      正则表达式)
    • GNU

      sed

      *增加选项

      --posix

      为了确保POSIX只提供功能(严格地说,您不需要这一点,但是没有它,您可能会无意中使用非POSIX特性而不注意到这一点;

      警告--posix 本身

      POSIX-符合规定)
    • 使用POSIX专用特性意味着更严格的格式化要求(放弃GNU中提供的许多便利)。

      sed):

然而,双管齐下版本实现扩展符合POSIX标准:

  • 什么它们实现的扩展不同

    (GNU)

    sed

    实现更多)。
  • 即使是那些

    扩展它们双管齐下实施语法部分不同.

如果您需要支持这两个平台(讨论差异):

  • 不相容

    特征:
    • BSD

      sed总是追加换行符

      对于输出,即使输入行不以一个结尾。
    • GNU

      sed保留“尾换行符”状态。

      ,也就是说,只有当输入行以1结尾时,它才会追加换行符。
    • BSD

      sed

      *必须使用

      -i ''

    • GNU

      sed

      *必须使用

      -i

      (相当于:

      -i''

      )-使用

      -i ''

      不起作用。
    • 使用

      -i期权争论

      (在没有备份的情况下就地更新)是不兼容的:
    • -i理智地打开每输入文件线路编号

      在……里面

      GNU sed

      最近

      的版本

      BSD sed

      (例如,在FreeBSD 10上),但是

      从10.12开始就不在MacOS上了.

      请注意,在不存在的情况下

      -i 

      版本数行

      累积

      跨输入文件。
    • 如果

      最活的,刚过去的输入行有一个尾随的新线

      (印刷本):
  • 共同

    特征:
    • 如果你限制你的

      sed

      BSD脚本

      sed

      支持,它们通常在GNU中工作。

      sed

      也是-除了使用特定于平台的显著例外

      扩展

      正则表达式特性

      -E

      ..显然,您还将放弃特定于GNU版本的扩展。见下一节。

指导方针跨平台支撑(OSX/BSD,Linux),由BSD版本更严格的要求驱动:

注意我用的是速记MacOSlinux的BSD和GNU版本sed因为它们是每个平台上的股票版本。但是,可以安装GNU。sed例如,在MacOS上使用自制带着brew install gnu-sed.

但当-r-E使用标志 (扩展),下面的说明相当于编写POSIX-符合 sed剧本。

  • 对于POSIX的遵从性,您必须将自己限制在

    POSIX Bres(基本正则表达式)

    ,不幸的是,顾名思义,这是相当基本的。


    警告

    *不要假定

    \|\+

    \?

    支持:而GNU

    sed

    支持他们(除非

    --posix

    ),BSD

    sed

    不-这些特性是

    符合POSIX标准。


    \+\? 能,会,可以被模仿

    以符合POSIX的方式:


    \{1,\}

    \+,
    \{0,1\}

    \?,
    \|(交替)不可能

    不幸的是。
  • 对于更强大的正则表达式,使用-E(而不是-r)支持埃雷斯扩展正则表达式)(GNU)sed不记录-E的别名-r较新BSD版本sed,例如FreeBSD 10,现在也支持-r,但MacOS版本在10.10的时候).
    警告*即使使用-r / -E意味着您的命令定义为符合POSIX标准的,您必须仍然限制自己扩展正则表达式..遗憾的是,这意味着您将无法使用几个有用的结构,特别是:

    • 词边界断言,因为它们是

      平台专用

      (例如,

      \<

      在Linux上,

      [[:<]]

      在OS X上)。
    • 回引

      内正则表达式

      (与捕获替换字符串中的组匹配的“反向引用”相反)

      s

      函数调用),因为BSD

      sed

      不支持他们

      扩展

      雷克斯(但奇怪的是,在

      基本

      在它们是POSIX的地方-授权)。
  • 控制字符转义序列,如\n\t:

    • 仅Linux:


      sed 's/-/\t/' <<<$'a-b' # -> 'a<tab>b'

    • MacOS

      Linux:


      sed 's/-/'$'\t''/' <<<'a-b'
      sed 's/-/'"$(printf '\t')"'/' <<<'a-b'

    • 仅Linux:


      sed 's/\t/-/' <<<$'a\tb' # -> 'a-b'

    • MacOS

      Linux:


      sed 's/'$'\t''/-/' <<<$'a\tb'            # ANSI C-quoted string
      sed 's/'"$(printf '\t')"'/-/' <<<$'a\tb' # command subst. with printf

    • 在……里面

      雷克斯

      (在用于选择的模式中和在

      s

      函数),假设只有

      \n

      被识别为转义序列(很少使用,因为模式空间通常是

      单株

      线路(不终止)

      \n

      ),但不在

      字符类

      ,所以,例如,

      [^\n]

      不工作;(如果您的输入不包含控制字符。除

      \t

      ,你可以模仿

      [^\n]

      带着

      [[:print:][:blank:]]

      否则,拼接控制字符。在AS

      文字[2]) - 通常,将控制字符包括为文字,或者通过剪接Ansi C引号字符串(例如,$'\t')在支持它的shell中(bash,KSHzsh),或通过命令替换使用printf(例如,"$(printf '\t')").

    • 在……里面替换字符串s指挥部,假设不支持控制字符转义序列。,所以,再一次,包括控制字符。如文字,如上所示。

    • 同为文本参数ia功能不要使用控制字符序列。-见下文。

  • 标签和分支

    *标签和标签名称

    论辩

    b

    t

    功能

    必须后面跟着一个文字纽线或拼接$'\n'

    ..或者,使用多个

    -e

    选项,并在标签名称之后终止每个选项。
    • 或者(实际换行符):


      sed -n '/a/ bLBL d; :LBL p' <<<$'a\nb'

    • 或(拼接)

      $\n

      (实例):


      sed -n '/a/ bLBL'$'\n''d; :LBL'$'\n''p' <<<$'a\nb'

    • 或(倍数)

      -e

      (备选方案):


      sed -n -e '/a/ bLBL' -e 'd; :LBL' -e 'p' <<<$'a\nb'

    • 仅Linux:


      sed -n '/a/ bLBL; d; :LBL p' <<<$'a\nb' # -> 'a'

    • MacOS

      Linux:
  • 功能

    ia用于插入/附加文本跟随函数名\,后面跟着一个文字纽线或拼接$'\n'

    指定文本参数之前。
    • -e

      ,文本参数在MacOS(bug?)中的输出上没有以换行符结尾,这是令人费解的。
    • 不要使用控制字符转义。

      比如

      \n

      \t

      在Text参数中,因为它们仅在Linux上被支持。
    • 如果文本参数因此具有实际的内部换行符,

      \

      -逃离他们。
    • 如果要在Text参数之后放置其他命令,则必须使用(未转义的)换行符(无论是文字的还是插入的)终止它,或者继续使用单独的

      -e

      选项(这是适用于所有版本的一般要求)。
    • 仅Linux:


      sed '1 i new first line' <<<$'a\nb' # -> 'new first line<nl>a<nl>b'

    • MacOS

      Linux:


      sed -e '1 i\'$'\n''new first line' <<<$'a\nb'

    • 注:
  • 功能列表

    (包含在

    {...}), 也要确保终止最活的,刚过去的函数,关闭前}..;.

    • 仅Linux:
    • sed -n '1 {p;q}' <<<$'a\nb' # -> 'a'

    • MacOS

      Linux:
    • sed -n '1 {p;q;}' <<<$'a\nb'


GNUsed-具体特征BSD失踪sed共:

如果您需要支持这两个平台,您可能会错过GNU特性:


[1]MacOSsed版本是老一点比其他类似BSD的系统上的版本,如FreeBSD和PC-BSD.不幸的是,这意味着您不能假设在FreeBSD中工作的特性将在MacOS上[同样]工作。

[2]ANSI C-引号字符串$'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'包含除ASCII以外的所有ASCII控制字符。\n(和nul),所以您可以将它与[:print:]对于一个相当健壮的仿真[^\n]:
'[[:print:]'$'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'']


查看完整回答
反对 回复 2019-07-03
?
慕田峪9158850

这似乎有点奇怪,但请尝试:

sed -i '' 's/\\n/\
/g' test1.txt

也就是说,使用实际新线代替\n.

原因是你有个奇怪的sed!有关详细信息,请参阅Macsed手册:https:/developer.apple.com/Library/mac/Document/达尔文/Reference/ManPages/man 1/sed.1.html

在描述s那里的指挥部说:

A line can be split by substituting a newline character into it.  To specify
a newline character in the replacement string, precede it with a backslash.

同时,在对-i选项,它表示扩展不是可选的,如果不需要扩展,则必须指定一个空参数。所以最后一切都是有意义的!


查看完整回答
反对 回复 2019-07-03

添加回答

回复

举报

0/150
提交
取消
意见反馈 邀请有奖 帮助中心 APP下载
官方微信