sed:替换 /etc/fstab 中的条目

sed:替换 /etc/fstab 中的条目

我正在强化我们的一些系统。作为强化过程的一部分,我需要更新 /etc/fstab 中的一些条目以限制某些分区的功能。

话虽如此,我希望能够使用 sed 内联替换来更新行。以下是当前 /etc/fstab 中的片段:

# /etc/fstab
# Created by anaconda on Wed Feb 21 09:37:23 2018
/dev/mapper/vg1-lv_root /                       ext4    defaults        1 1
/dev/mapper/vg1-lv_home /home                   ext4    defaults        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0

运行 sed 命令后,我希望文件如下所示:

# /etc/fstab
# Created by anaconda on Wed Feb 21 09:37:23 2018
/dev/mapper/vg1-lv_root /                       ext4    defaults        1 1
/dev/mapper/vg1-lv_home /home                   ext4    defaults,nodev        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0

基本上,我需要将“nodev”添加到 ext[2-4] 的所有行(不是根分区)。

我组合在一起的 sed 命令接近执行此操作,但无论出于何种原因,我无法使正则表达式与“/”分区不匹配,因此它也总是更新该行。

sed '/^[^#].*ext[2-4]/s/defaults/defaults,nodev/g' /etc/fstab

我想关闭由空格包围的“/”,而不是 vg1-lv_root。以下方法有效,但我不喜欢该解决方案,因为它很笨重:

sed '/^[^#].*ext[2-4]/s/defaults/defaults,nodev/g' /etc/fstab | sed '/^[^#].*root.*ext[2-4]/s/defaults,nodev/defaults/' > /etc/fstab

答案1

您可以使用awk添加逻辑来添加字符串并column重新格式化最终输出文件。假设您有/etc//tmp/文件夹的写入权限

tempfile=$(mktemp /tmp/tmpfile.XXXXXXXX)

/tmp/这将在您可以将输出写入的路径中创建临时文件awk并将其重定向回原始文件

awk '$3 ~ "ext[2-4]"{ $4=$4",nodev" }1 ' /etc/fstab | column -t > "$tempfile" && mv -- "$tempfile" /etc/fstab

column -t部分只是多余的,需要使输出文件更具可读性,而不是使其变得无序和笨重。

答案2

这是一个更简单的sed方法:

$ sed -E 's|(\s/\S+\s+ext[2-4]\s+defaults)|\1,nodev|' fstab 
# /etc/fstab
# Created by anaconda on Wed Feb 21 09:37:23 2018
/dev/mapper/vg1-lv_root /                       ext4    defaults        1 1
/dev/mapper/vg1-lv_home /home                   ext4    defaults,nodev        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0

诀窍是查找空格后跟 a/和一个或多个非空格字符 ( \s/\S+),ext[2-4]然后查找前面有空格 ( \s+ext[2-4])、更多空格和 的情况defaults。这应该只匹配您感兴趣的情况。因此,如果匹配,请将整个匹配项替换为自身加上nodev​​: \1,nodev

不过,我不确定它的便携性如何。-E许多实现都支持 for 扩展正则表达式,sed但它不是 POSIX。对于更便携的方法,您可以在 Perl 中尝试相同的想法:

$ perl -pe 's|(\s/\S+\s+ext[2-4]\s+defaults)|\1,nodev|' fstab 
# /etc/fstab
# Created by anaconda on Wed Feb 21 09:37:23 2018
/dev/mapper/vg1-lv_root /                       ext4    defaults        1 1
/dev/mapper/vg1-lv_home /home                   ext4    defaults,nodev        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0

在这两种情况下,要就地编辑文件,请使用-i

perl -i -pe 's|(\s/\S+\s+ext[2-4]\s+defaults)|\1,nodev|' fstab 
sed -E 's|(\s/\S+\s+ext[2-4]\s+defaults)|\1,nodev|' fstab 

或者,对于 BSD 或 OSX sed

sed -i '' -E 's|(\s/\S+\s+ext[2-4]\s+defaults)|\1,nodev|' fstab 

请注意,上述假设该defaults选项要么是唯一的一个,要么至少是最后一个。如果你有类似的东西,他们就会失败nodev,defaults

答案3

当然,在发布问题十分钟后,我终于能够通过以下命令让它执行我想要的操作:

sed -r '/^[^#].*[ \t]+\/[^[:space:]].*ext[2-4]/s/defaults/defaults,nodev/g' /etc/fstab

如果有人有更清晰或更简单的答案,我很想听听。谢谢!

答案4

排除匹配很难维持。只匹配您想要的分区会更安全。并且,如果仅匹配一行,则不需要尾随“g”。

sed -r 's#(/home\s.*defaults)\s#\1,nodev #' /etc/fstab 

相关内容