如何有选择地修改文件中的行,其中修改取决于将选择行作为一个整体而不是单独分析

如何有选择地修改文件中的行,其中修改取决于将选择行作为一个整体而不是单独分析

长话短说我需要对齐 fstab 中条目的列,同时忽略注释:

/dev/foo              /foo         ext4        defaults   0    2
# comment line 1
/dev/bar /bar ext4 defaults 0 2
# comment line 2
UUID=1234567890     /baz      ext4      defaults   0       2

应该成为

/dev/foo         /foo  ext4  defaults  0  2
# comment line 1
/dev/bar         /bar  ext4  defaults  0  2
# comment line 2
UUID=1234567890  /baz  ext4  defaults  0  2

理想情况下,只需一个俯冲命令。

</tldr>

我的fstab由注释行中的一大块文档组成,以字段描述结尾,最后是条目。条目部分散布着注释行。

# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>

# table entries begin ...

我想使用column -t命令或等效命令对齐输入行中的列,但想忽略注释。如果我不忽略注释行,即使它们也会被对齐。在 vim 中编辑文件时,我可以直观地选择从第一个条目开始的行并运行,'<,'> !grep '^[^\#]' | column -t但 grep 会过滤掉注释行,因此,它们不会出现在输出中,这会替换 vim 中的选择。我无法在每个匹配行上单独运行列命令,因为column这样不行。

有没有一个简单的命令可以完成这个任务?它不需要在 vim 中实现,因为我可以简单地将它委托给内部的外部命令。

答案1

tr -s \[:blank:] \  </etc/fstab |       # squeeze all tabs/spaces to 1 space
sed 's/^#/ # # # # # #/'        |       # create 6 tiny comment fields
column -t                       |       # get columns
sed '/^\( *#\)\{6\}/{s//#/;s/  */ /g;}' # fix and squeeze spaces for comments

相关内容