Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 在bash中,sed和cat>&燃气轮机;_Linux_Bash_Sed_Scripting_Hosts - Fatal编程技术网

Linux 在bash中,sed和cat>&燃气轮机;

Linux 在bash中,sed和cat>&燃气轮机;,linux,bash,sed,scripting,hosts,Linux,Bash,Sed,Scripting,Hosts,我试图用我的脚本替换/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 [[

我试图用我的脚本替换/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 
并使用sed命令将该行(如果找到)替换为nothing,但随后添加,例如

192.169.1xx.xxx mynas01 
我不得不这么做(?)因为我的LAN网络地址经常变化(确切地说:在每个工作日,但不总是在工作会话中),所以每次编辑/etc/hosts文件都不是很有用,即使是设置SNMP之类的东西(对于两台服务器)对我来说有点太多的开销-我只想把这个脚本放在cron作业或rc.local中,以避免SMB查找

现在我的问题是:如果我这样做,在文件结束后和/或在添加的文本之间会有更多的空换行符,我如何避免这种情况,有没有更短的方法

到目前为止,我得到的结果是(/etc/hosts):


谢谢

只需使用
grep-v
从文件中删除您不喜欢的行即可。它比现在的
grep
之后的
sed
容易得多,而且不会留下空白行。

假设您有一个类似于这样的/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

问题是,您的
sed
命令没有删除感兴趣的行,而是将其变为一个空行,因此实际上,您在为其添加新行时会清空一个旧的NAS条目,这会不断添加行

改用以下
sed
命令删除匹配行:

sr="/${nas_name}/ d"
或者,更确切地说,为了排除误报:

sr="/[[:blank:]]${nas_name}[[:blank:]]*$/ d"
由于使用了双引号字符串,因此通常必须对
$
字符使用
\$
。外壳不应膨胀。
但是,shell只留下一些语法上无效的变量引用,因此
$/
按原样传递给
sed

为了更严格地分离shell扩展部分(双引号)和Sed脚本(单引号),您可以使用以下内容,但是这更难理解:
sr='/[[:blank:]'“${nas_name}”[[:blank:]*$/d'
。不过,总的来说,这是一种值得采用的方法


请注意,可以通过多种方式简化脚本,包括使用单个
sed
命令直接更新现有条目,而不是首先使用
sed
删除旧条目,然后使用
cat
添加新条目,但grep-v返回一个grep匹配的反向搜索。如何对两个或多个字符串(mynas01、mynas02、mynas03…)执行此操作?
grep-v
可能稍微容易一些,但如果您还希望就地更新输入文件(如此处所示),
sed-I
非常方便,OP唯一的问题是使用
s
函数将匹配行替换为空字符串,而不是使用
d
函数将其删除。@程序员:
egrep-v'mynas[0-9]+'
是一种方法。正如您所看到的,有一个字符串列表(或者更好:我想更改的nas的名称列表:mynas01,…)原始的/etc/hosts文件是什么样子的?不清楚您的答案与问题的关系。问题是为什么每次运行后文件中都会出现新的空行,以及如何避免它们。(有效地)更新条目的部分已经可以很好地工作了——尽管它比需要的更麻烦(先删除旧条目,然后附加更新版本)。虽然如你所建议的那样使用直接替换是更好的,但你没有抓住问题的关键。
sr="/${nas_name}/ d"
sr="/[[:blank:]]${nas_name}[[:blank:]]*$/ d"