所以我的文件中填充了这样的行:
/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
我已经尝试了sed
和awk
的 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
),我在这里做的很简单。
答案 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