从每个块中的最后一个元素中删除逗号

Remove comma from last element in each block

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

heading1(
a,
b,
c,
);

some more text

heading2(
d,
e,
f,
);

这必须使用 bash 而不是 Perl 或 Python 等,因为我的目标系统上没有安装这些。我可以使用 sedawk 等,但我不能将 sed 与 -z 参数一起使用,因为我使用的是该实用程序的旧版本。

所以 sed -zi 's/,\n);/\n);/g' $file 关闭了 table。

如有任何帮助,我们将不胜感激。谢谢

这可能适用于您的 sed 版本。然后又可能不会。

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

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

使用sed大致有两种方法:

  1. 在模式中保留多行space;或
  2. 保留前一行 space。

仅使用模式 space 意味着非常简洁的版本:

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

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

这也依赖于 NPD 的隐式行为,这些行为会根据达到 end-of-input 的时间而变化。阅读 man sed 了解详细信息。

将其展开为每行一个命令得到:

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

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

  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 '

首先无条件地将第一行从模式 space 复制到保留 space,然后删除模式 space(强制跳到下一行)

    1 {
      h
      d
    }

对于以 ')' 开头的每一行,交换模式 space 并按住 space(所以你现在在模式 space 中有前一行),删除尾随逗号(如果有),然后再次换回:

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

现在将模式 space 与保持 space 交换,因此保持 space 现在保持 当前 线和模式 space 保留上一行。

    x

通常模式 space 的内容会在到达脚本末尾时发送到输出,但我们还有一个情况需要先处理。

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

    $ {
      p
      x
      s/,$//
    }

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

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

  '

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

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

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

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

带有 GNU sed 的更简单和更易读的版本(你没有):

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

使用awk:

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

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

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

一些输出:

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

这可能适合您 (GNU sed):

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

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

否则,如果下一行与上面不匹配,print/delete第一行并重复。