Você pode fazer isso com sed - é Turing-complete. Mas não é a melhor ferramenta para o trabalho. Sed não tem uma maneira conveniente de lembrar que já foi feito um substituto.
O que você pode fazer relativamente facilmente com o sed é colocar todas as linhas em branco iniciando /swapfile
e adicionar uma nova no final:
sed -i '$! s/^\/swapfile[\t ]//; $s/\(^\/swapfile.*\)\?$/\n\/swapfile none swap sw/' /etc/fstab
mas além disso, estamos entrando rapidamente em um território onde eu não deixaria esse código sed para outro administrador de sistema manter, especialmente quando uma combinação simples e legível de comandos de shell faria um trabalho melhor:
{ </etc/fstab grep -v '/swapfile[\t ]'; echo '/swapfile none swap sw'; } >/etc/fstab.new && mv /etc/fstab.new /etc/fstab
Se você quiser preservar a posição existente da linha /swapfile
se ela estiver lá e apenas modificar o arquivo se precisar ser modificado, uma combinação de lógica shell e awk é uma ferramenta melhor. Eu usei várias linhas aqui para maior clareza, mas você pode colocar todo o código na mesma linha, se quiser. Como bônus, se o arquivo já continha a linha desejada (com espaçamento exato), ele não será modificado.
awk '
/\/swapfile[\t ]/ {if (replaced) {next}
else {replaced=1; print "/swapfile none swap sw"}}
1 {print}
END {if (!replaced) print "/swapfile none swap sw"}
' /etc/fstab >/etc/fstab.new &&
if cmp -s /etc/fstab.new /etc/fstab.new; then
rm /etc/fstab.new;
else
mv /etc/fstab.new /etc/fstab;
fi