在不中断间距的情况下在列中插入文本

时间:2014-08-06 17:13:54

标签: bash perl awk sed

所以我的文件中填充了这样的行:

/dev/VolGroup00/LogVol00 /                       ext3    defaults        1 1
LABEL=/boot             /boot                   ext3    defaults        1 2
tmpfs                   /dev/shm                tmpfs   mode=35        0 0

我试图添加一些文字(我们称之为ADD)第4列,以便输出

/dev/VolGroup00/LogVol00 /                       ext3    defaultsADD        1 1
LABEL=/boot             /boot                   ext3    defaultsADD        1 2
tmpfs                   /dev/shm                tmpfs   mode=35ADD        0 0

我已经尝试了sedawk SED

$ sed -r 's/(\s+\S+\s+\S+\s+\S+)(\s+\S+\s+\S$)/\1ADD\2/' fstab
/dev/VolGroup00/LogVol00 /                       ext3    defaultsADD        1 1
LABEL=/boot             /boot                   ext3    defaultsADD        1 2
tmpfs                   /dev/shm                tmpfs   mode=35ADD        0 0

这完全有效但sed看起来很恶心 的 AWK

$ awk -v OFS='\t' '{$4=$4"ADD"; print}' fstab 
/dev/VolGroup00/LogVol00        /       ext3    defaultsADD        1       1
LABEL=/boot     /boot   ext3    defaultsADD        1       2
tmpfs   /dev/shm        tmpfs   defaultsADD        0       0

虽然命令本身是可读的,但输出会丢失我希望保留的原始间距。

所以我看到了我的问题的三种可能的解决方案:

  • 更好看的sed命令
  • 使用awk保留间距的方法
  • 保留间距的其他一些好的(简短的,可读的)外观命令(可能是perl

编辑:
我希望这是一个就地编辑(覆盖fstab 使用sed -i'' -r 's/...有效,但awk无法处理就地编辑。我知道我可以将它输出到一个文件并用它覆盖fstab,但这有点长(awk ... > temp && mv -f temp fstab),我在这里做的很简单。

7 个答案:

答案 0 :(得分:3)

这个sed是否漂亮但有效是有争议的。

sed -r 's/((\s+\S+){3})/\1ADD/' fstab

编辑:修正了它,看起来好一点。

答案 1 :(得分:2)

使用Perl稍微不那么丑陋的正则表达式:

perl -i.bak -pwe 'next if /^#/; s/^(?:\S+\s+){3}\S+\K/ADD/' /etc/fstab

请注意,Perl 5.10中添加了\K转义符。由于我假设您不想向它们添加任何内容,因此会跳过注释行。 -i标记执行就地编辑,将原始副本保存到/etc/fstab.bak

答案 2 :(得分:1)

再次使用sed:

sed -r 's|((\s+\S+){3})(.*)|\1ADD\2|' /etc/fstab

它重复\s+\S+模式三次并将结果放入\1,然后使用.*捕获其后的所有内容并将其放入\2

答案 3 :(得分:1)

awk '{gsub($4, $4"ADD"); print}' fstab似乎对我有用。

答案 4 :(得分:0)

您的解决方案似乎很好。唯一缺少的是格式化。请使用column -t

... | column -t

答案 5 :(得分:0)

如果您喜欢sed,但发现它没有吸引力,那么您可能需要进行轻微的重构。

f='\s+\S+'
sed -i.bak -r "s/($f$f$f)($f$f$)/\1ADD\2/" fstab

答案 6 :(得分:0)

您可能喜欢这个Perl解决方案。循环中的第二行允许以空格开头的行,并且可能不需要那么复杂。

它希望输入文件的路径在命令行上作为参数。

use strict;
use warnings;

while (<>) {
  my @fields = split /(\s+)/;
  $fields[/^\S/ ? 6 : 8] .= 'ADD';
  print @fields;
}

<强>输出

/dev/VolGroup00/LogVol00 /                       ext3    defaultsADD        1 1
LABEL=/boot             /boot                   ext3    defaultsADD        1 2
tmpfs                   /dev/shm                tmpfs   mode=35ADD        0 0
相关问题