我正在尝试使用我的脚本替换/ etc / hosts文件中的某些行:
#!/bin/bash
hosts_file_path="/etc/hosts"
nas_servers=( 'mynas01' 'mynas02' )
strange_string="<00>"
for nas_name in ${nas_servers[@]}; do
printf '%ls\n' "$nas_name"
r="$(nmblookup "$nas_name")"
if [[ ! -z "$r" ]] && [[ "$r" != "name_query" ]]; then
l=${#r}
ls=${#strange_string}
cl=$(($l-$ls))
echo "$cl"
s="${r:0:cl}"
printf '"%ls"\n' "$s"
res="$(grep -i "$nas_name" "$hosts_file_path")"
echo "$res"
if [ ! -z "$res" ]; then
sr="s/.*${nas_name}.*//g"
echo "$sr"
sed -i "$sr" "$hosts_file_path"
fi
printf '%ls\n' "$s" >> "$hosts_file_path"
fi
done
搜索例如对于像
这样的行192.168.1xx.xxx mynas01
并用sed命令将该行(如果已找到)替换为空,但之后添加,例如到
192.169.1xx.xxx mynas01
我必须这样做(?)这是因为我的LAN网络地址经常变化(确切地说:在每个工作日,但并不总是在工作会话中),因此每次/ etc / hosts文件都不会编辑非常有用,甚至设置像SNMP这样的东西(对于两台服务器)对我来说有点太多开销 - 我只是想把这个脚本放在一个cron作业或rc.local中,以避免smblookups。
现在我的问题:如果我以这种方式制作,在文件结束之后会有更多空的换行符和/或添加的文本之间,我如何避免这种情况,是否有更短的方法呢?
直到现在我得到了结果(/ etc / hosts):
127.0.0.1 localhost
127.0.1.1 hostname.fqdn.example.com hostnam
(^ the space here got more and more by each call of my script, more newlines and more newlines)
192.168.1xx.101 mynas01
192.168.1xx.102 mynas02
由于
答案 0 :(得分:1)
只需使用grep -v
从文件中删除您不喜欢的行。比sed
之后的grep
要容易得多,而且它不会让你留下空白。
答案 1 :(得分:1)
问题是您的sed
命令,而不是删除感兴趣的行,将其转换为空行,所以实际上你删除旧的NAS条目,同时为其添加新行,这样可以不断添加行。
使用以下sed
命令,删除匹配的行:
sr="/${nas_name}/ d"
或更有力地排除误报:
sr="/[[:blank:]]${nas_name}[[:blank:]]*$/ d"
由于使用了双引号字符串,因此您通常必须使用\$
作为$
字符。 shell应不展开。
但是,shell会留下一些不仅仅是语法上有效的变量引用,因此$/
按原样传递给sed
。
为了更严格地分离shell扩展部分(双引号)和Sed脚本(单引号),您可以使用以下内容,但更难以阅读:sr='/[[:blank:]]'"${nas_name}"'[[:blank:]]*$/ d'
。但一般来说,这是一种有价值的方法。
请注意,您的脚本可以通过多种方式进行简化,包括使用单个sed
命令直接更新现有条目,而不是先使用sed
删除旧条目,然后添加新条目cat
。
答案 2 :(得分:-1)
假设您有一个看起来像这样的/ etc / hosts文件
192.168.111.000 mynas01
192.168.222.000 mynas01
192.168.333.000 mynas01
000.192.168.000 mynas01
你只需要这样做:
cat /etc/hosts | sed 's/^192\.168\./192\.169\./'
你得到了
192.169.111.000 mynas01
192.169.222.000 mynas01
192.169.333.000 mynas01
000.192.168.000 mynas01