有没有一种方法可以嵌套sed替换操作?

5
我想改变文件中每一行的格式,并在其中一个匹配组上运行另一个替换操作。
例如,我可能有一个简单的三列CSV文件(没有转义字符),我想将其放入另一种格式。
sed -r 's/^([a-z]+),([a-z]+),([a-z]+)$/\1: \3 (\2)'
# would turn "comma,separated,values"
# into       "comma: values (separated)"

然而,我还想从第二列中删除所有的元音字母,即在 \2 上运行 s/[aeiou]//g 命令。
有没有解决这种嵌套替换问题的好方法?请假设两个替换都很复杂,并且这只是个例子。
我的sed不是GNU sed 4.0版本。

你能不能不把一个sed管到第二个sed里面? - NorthGuard
@inTide:我不想移除所有的元音字母,只想从第二列中移除。 - Tim
好的,首先使用sed删除逗号之间的所有元音字母,然后使用第二个sed将第一个逗号替换为,将第二个逗号替换为(). - NorthGuard
@inTide:我正在寻找一种适用于所有格式且不需要我写两次几乎相同模式的解决方案。我知道sed具有动态范围规定的许多功能,但不知道如何将它们用于此问题。 - Tim
那么你的sed是哪个版本? - Beta
@Beta:我刚在这里发布了问题:哪个sed版本不是GNU sed 4.0? - Tim
2个回答

1

我认为对于这个问题,你最好使用 awk ,以便更轻松地操作字段。

echo "gaviidae,gruidae,picidae" | awk -F "," '{gsub(/[aeiou]/, "", $2); printf("%s: %s (%s)\n", $1, $3, $2)}'

输出:

gaviidae: picidae (grd)

我不会使用 awk,有没有一种类似于 sed 的简单匹配方式?你的命令似乎是在逗号上分割的,所以它并不是很通用。 - Tim
字段分隔符由-F参数设置。它接受正则表达式,但不是以使用反向引用的方式编写的。如果您的格式需要更复杂的解析才能分割成字段,则我承认 awk 并不是很有帮助。 - Simon

1

这段代码有点晦涩(就像几乎所有非平凡的sed一样),但它能完成任务。它利用了你想要修改的单词在末尾的事实——如果你想让它到达其他位置,同样的技巧也可以使用,但命令会稍微长一些。

sed 'h;s/.*,([a-z]+),.*/(\1)/;s/[aeiou]//g;x;s/([a-z]+),[a-z]+,([a-z]+)/\1: \2 /;G;s/\n//'

或者用英语说:“将副本保存在保持缓冲区中,删除除第二个单词以外的所有内容,去除元音字母,交换缓冲区,重新排列单词(删除中间一个),将另一个缓冲区添加到末尾,移除换行符”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接