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

sg24os4d  于 2022-11-04  发布在  Unix
关注(0)|答案(6)|浏览(151)

我得到了一个包含以下内容的文件,并希望删除最后一个逗号(在本例中,是“c”和“f”后面的逗号)。

heading1(
a,
b,
c,
);

some more text

heading2(
d,
e,
f,
);

我可以使用sedawk等,但是我不能使用带-z参数的sed,因为我使用的是旧版本的实用程序。
所以sed -zi 's/,\n);/\n);/g' $file是不可能的。
任何帮助将不胜感激。谢谢

pgky5nke

pgky5nke1#

这在您的sed版本中可能有效,但也可能无效。

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

粗略翻译:“将此行与保留空格交换。如果这是第一行,则不再对它执行其他操作。将保留空格追加到缓冲区中的该行(这样您就可以看到最后一行和当前行)。如果您所看到的内容以分号结尾,请删除逗号。如果您不在文件的最后一行,请删除您所看到的两行内容中的第二行。(即当前行,我们将在看到下一行后处理)。”

7xzttuei

7xzttuei2#

使用awk、RS="^$"读入整个文件,使用regex替换部分文本:

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

部分输出:

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

xxe27gdn3#

在所示的输入上,这应该可以与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
gwbalxhn

gwbalxhn4#

使用awk

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

lrpiutwd5#

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

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

如果一行以逗号结尾,则提取下一行;如果该行以);结尾,则删除逗号。
否则,如果下一行与上面的不匹配,则打印/删除第一行并重复。

s6fujrry

s6fujrry6#

使用sed大致有两种方法:
1.在图案空间中保留多条线;或
1.将上一行保留在保留空间中。
仅使用模式空间意味着非常简洁的版本:

sed 'N; s/,[[:space:]]*\n*[[:space:]]*)/)/; P; D'

这依赖于模式空间能够容纳多行,并且能够将换行符与\n匹配。不是所有的sed版本都能做到这一点,但GNU sed可以。
这还依赖于NPD的隐式行为,这些隐式行为会随着输入结束的时间而改变。
将其展开为每行一个命令,得到:

sed '
    N
    s/,[[:space:]]*\n*[[:space:]]*)/)/
    P
    D
'

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

sed '1 { h; d; }; /^)/ { x; s/,[[:space:]]*$//; x; }; x; $ { p; x; s/,$//; }'

展开我们得到:

sed '
    1 {
      h
      d
    }
    /^)/ {
      x
      s/,[[:space:]]*$//
      x
    }
    x
    $ {
      p
      x
      s/,[[:space:]]*$//
    }
  '

打破这一点:接下来是一个“sed脚本”;因此只需在它前后加上“”并在它前面加上“sed”:

sed '

首先,无条件地将第一行从模式空间复制到保留空间,然后删除模式空间(强制跳到下一行)
对于以')'开头的每一行,交换模式空格并保留空格(这样您现在在模式空格中有了上一行),删除尾部逗号(如果有),然后再交换回来:

/^)/ {
      x
      s/,[[:space:]]*$//
      x
    }

现在用保留空间交换模式空间,这样保留空间现在保留 * 当前 * 行,模式空间保留前一行。

x

通常情况下,当到达脚本末尾时,模式空间的内容将被发送到输出,但是我们首先还要处理一个案例。
在最后一行,打印前一行,然后交换以检索最后一行,然后(因为我们到达了脚本的结尾)也打印它。如果您不想这样做,可以删除下面的s命令。

$ {
      p
      x
      s/,[[:space:]]*$//
    }

在到达sed脚本的末尾时,将打印模式空间;所以结尾没有“p”。
如前所述,请从头开始关闭报价。

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

相关问题