【问题标题】:Remove comma from last element in each block从每个块中的最后一个元素中删除逗号
【发布时间】:2022-02-18 22:13:40
【问题描述】:

我有一个包含以下内容的文件,并且想要删除最后一个逗号(在本例中,是 'c' 和 'f' 之后的逗号)。

heading1(
a,
b,
c,
);

some more text

heading2(
d,
e,
f,
);

这必须使用 bash 而不是 Perl 或 Python 等,因为它们没有安装在我的目标系统上。我可以使用sed、awk 等,但我不能使用带有-z 参数的sed,因为我使用的是旧版本的实用程序。

所以sed -zi 's/,\n);/\n);/g' $file 不在讨论范围内。

任何帮助将不胜感激。谢谢

【问题讨论】:

    标签: bash unix sed


    【解决方案1】:

    这可能适用于您的 sed 版本。那么它可能不会。

    sed 'x;1d;G;/;$/s/,//;$!s/\n.*//' $file
    

    粗略翻译:“将此行与保留空间交换。如果这是第一行,则不再使用它。将保留空间附加到缓冲区中的行(这样您就可以看到最后一行当前行)。如果您的内容以分号结尾,请删除逗号。如果您不在文件的最后一行,请删除您拥有的两行中的第二行(即当前行,我们将等我们看到下一个后再处理)。”

    【讨论】:

    • 这似乎几乎可以工作。它会删除最后一部分的最后 2 个逗号。
    • 更正,它复制了最后一个元素。在我的例子中,它就像 ``` heading1(a, b, c);更多文本标题2(d, e, f f);
    • @sharkbites: [facepalm] 我怎么没注意到?正在编辑...
    【解决方案2】:

    使用 awk、RS="^$" 读取整个文件并使用正则表达式替换部分文本:

    $ awk -v RS=^$ '{gsub(/,\n\);/,"\n);")}1' file
    

    一些输出:

    heading1(
    a,
    b,
    c
    );
    ...
    

    【讨论】:

      【解决方案3】:

      这应该在显示的输入上与 GNU sed 和 BSD sed 一起使用:

      sed -e ':a' -e '/,\n);$/!{N' -e 'ba' -e '}' -e 's/,\n);$/\n);/' file.txt
      

      我们连接模式空间中的行,直到它以,\n); 结尾。然后我们删除逗号,打印(默认)并用新行重新开始循环。

      使用 GNU sed 的更简单、更易读的版本(您没有):

      sed ':a;/,\n);$/!{N;ba};s/,\n);$/\n);/' file.txt
      

      【讨论】:

      • 嗯,我不知道为什么,但第一个例子似乎对我不起作用。
      • 似乎对我不起作用是什么意思?我刚刚对您提供的确切输入示例进行了测试,并且它在两个 sed 上都按预期工作。
      • 我也这样做了,三重检查我得到了所有字符。我得到:标题1(a,b,c,dn);标题2(e,f,g,hn); (在你问之前 - 是的,我逃脱了 n's )。我猜它只是不适用于我的 sed 版本
      • 有趣。这是什么版本的sed?我不明白你接受的(优秀的)解决方案是如何使用\n 的,我想了解一下。
      • 第一个解决方案也适用于我,但请注意我的解决方案在搜索模式中使用\n,而此解决方案在替换字符串中使用它。我记得我曾经拥有一个可以处理一个但不能处理另一个的 sed 版本。如果\n 在 sed 脚本中间被替换为实际的换行符,我敢打赌这个解决方案将适用于 OP。 (出于这个原因,我讨厌那个版本的 sed。)
      【解决方案4】:

      使用awk:

      awk '
      $0==");" {sub(/,$/, "", l)}
      FNR!=1 {print l}
      {l=$0}
      END {print l}'
      

      【讨论】:

        【解决方案5】:

        使用sed 大致有两种方法:

        1. 在模式空间中保留多行;或
        2. 将上一行保留在保留空间中。

        只使用模式空间意味着一个非常简洁的版本:

        sed 'N; s/,\n*)/)/; P; D'
        

        这依赖于模式空间能够容纳多行,并且能够将换行符与\n 匹配。并非所有版本的 sed 都可以做到这一点,但 GNU sed 可以。

        这还依赖于 N、P 和 D 的隐式行为,这些行为会根据何时到达输入结束而变化。阅读man sed了解血腥细节。

        展开到每行一个命令得到:

        sed '
            N
            s/,\n*)/)/
            P
            D
        '
        

        如果您只有 POSIX 版本的sed 可用,您还需要使用保留空间。在这种情况下,想法是当您在模式空间中看到 ) 时,您可以编辑保留空间中的行以删除逗号:

          sed '1 { h; d; }; /^)/ { x; s/,$//; x; }; x; $ { p; x; s/,$//; }'
        

        展开我们得到:

          sed '
            1 {
              h
              d
            }
            /^)/ {
              x
              s/,$//
              x
            }
            x
            $ {
              p
              x
              s/,$//
            }
          '
        

        打破它:接下来是一个“sed 脚本”;所以只需在它周围加上 '' 并在它前面加上“sed”:

          sed '
        

        首先无条件地将第一行从模式空间复制到保持空间,然后删除模式空间(这会强制跳到下一行)

            1 {
              h
              d
            }
        

        对于以 ')' 开头的每一行,交换模式空间和保持空间(因此您现在在模式空间中有前一行),删除尾随逗号(如果有),然后再次交换回来:

            /^)/ {
              x
              s/,$//
              x
            }
        

        现在将模式空间与保持空间交换,以便保持空间现在保持当前行,而模式空间保持上一行。

            x
        

        通常,当到达脚本末尾时,模式空间的内容将被发送到输出,但我们首先要处理另一种情况。

        在最后一行,打印上一行,然后交换以检索最后一行,然后(因为我们到达 script0 的末尾也打印它。此代码还将从最后一行删除尾随逗号,但这是可选;如果您不想要,可以将其删除。

            $ {
              p
              x
              s/,$//
            }
        

        到达 sed 脚本的末尾时,将打印模式空间;所以最后没有“p”。

        如前所述,从头开始关闭引用。

          '
        

        注意: 如果您需要向前扫描多行,而不是“x”来交换一行,使用“H;g”附加到保留空间,然后将保留空间复制到模式空间,然后“P;D”打印并删除到第一个换行符。 (H、P 和 D 是 GNU 扩展。)

        【讨论】:

          【解决方案6】:

          这可能对你有用(GNU sed):

          sed '/,$/{N;/);$/Ms/,$//M;P;D}' file
          

          如果一行以逗号结尾,则获取下一行,如果以 ); 结尾,则删除逗号。

          否则,如果以下行与上述不匹配,则打印/删除第一行并重复。

          【讨论】:

            猜你喜欢
            • 2015-08-05
            • 2019-03-19
            • 1970-01-01
            • 2021-10-02
            • 1970-01-01
            • 1970-01-01
            • 2011-11-18
            • 2020-02-05
            • 2013-11-24
            相关资源
            最近更新 更多