如何使用某些字符串过滤的awk从文件中删除一行

时间:2021-05-03 19:18:00

I have a file delimited by space. I need to write an awk command that receives a host name argument and it should replace the host name if it already defined in the file. It must be a full match not partially - if the file contains this host name: localhost searching for "ho" will fail and it will be added to the end of the file.

我有一个由空格分隔的文件。我需要编写一个接收主机名参数的awk命令,它应该替换主机名,如果它已在文件中定义的话。它必须是完全匹配而不是部分匹配 - 如果文件包含此主机名:localhost搜索“ho”将失败,它将被添加到文件的末尾。

another option is a delete: again awk receives host name argument and it should remove it from the file if exists.

另一个选项是删除:再次awk接收主机名参数,它应该从文件中删除它(如果存在)。

This is what I have so far: (It needs some enhancements)

这是我到目前为止:(需要一些增强功能)

if [ "$DELETE_FLAG" == "" ]; then
        # In this case the entry should be added or updated
        #    if clause deals with updating an existing entry
        #    END clause deals with adding a new entry
        awk -F"[ ]" "BEGIN { found = 0;} \
                { \
                        if ($2 == $HOST_NAME) { \
                                print \"$IP_ADDRESS $HOST_NAME\"; \
                                found = 1; \
                        } else { \
                                print \$0; \
                        } \
                } \
                END { \
                        if (found == 0) { \
                                print \"$IP_ADDRESS $HOST_NAME\";
                        } \
                } " \
        /etc/hosts > /etc/temp_hosts

else
        # Delete an existing entry
        awk -F'[ ]' '{if($2 != $HOST_NAME) { print $0} }' /etc/hosts > /etc/temp_hosts
fi

Thanks

2 个解决方案

#1


0  

you don't have to set FS to space, since by default FS is already spaces. And you don't have to use \. Use the -v option to pass in shell variables to awk. And there is no need to use semi-colon at end of every statement

您不必将FS设置为空格,因为默认FS已经是空格。而且你不必使用\。使用-v选项将shell变量传递给awk。并且在每个陈述的末尾都不需要使用分号

if [ "$DELETE_FLAG" == "" ]; then
        # In this case the entry should be added or updated
        #    if clause deals with updating an existing entry
        #    END clause deals with adding a new entry
        awk  -v hostname="$HOST_NAME" -v ip="$IP_ADDRESS" 'BEGIN { found = 0} 
        { 
            if ($2 == hostname) { 
                 print ip"  "hostname
                 found = 1
            } else { 
                 print $0 
            } 
        } 
        END { 
             if (found == 0) { 
                  print ip" "hostname
             } 
        }' /etc/hosts > /etc/temp_hosts

else
        # Delete an existing entry
        awk -v hostname="$HOST_NAME" '$2!=hostname' /etc/hosts > /etc/temp_hosts
fi

#2


0  

You should put the awk scripts inside single quotes and use variable passing to get the shell variables into the awk script. Then you won't have to do all that escaping. And I don't think the line-continuation backslashes and semicolons are necessary.

您应该将awk脚本放在单引号中并使用变量传递将shell变量放入awk脚本中。然后你不必做所有逃脱。我认为线条延续反斜杠和分号是不必要的。

Are the field separators spaces or are they spaces inside square brackets?

字段分隔符是空格还是方括号内的空格?

awk -F ' ' -v awkvar=$shellvar '
    BEGIN {
        do_something
    }
    {
        do_something_with awkvar
    }' file > out_file

Also, there's a slight danger that your tests will fail if the variable contains a string starting with a dash. There are at least a couple of ways to protect against this:

此外,如果变量包含以短划线开头的字符串,那么测试将会失败。至少有几种方法可以防止这种情况:

if [ "" == "$DELETE_FLAG" ]; then    # the dash isn't the first thing that `test` sees
if [ x"$DELETE_FLAG" == x"" ]; then  # ditto

#1


0  

you don't have to set FS to space, since by default FS is already spaces. And you don't have to use \. Use the -v option to pass in shell variables to awk. And there is no need to use semi-colon at end of every statement

您不必将FS设置为空格,因为默认FS已经是空格。而且你不必使用\。使用-v选项将shell变量传递给awk。并且在每个陈述的末尾都不需要使用分号

if [ "$DELETE_FLAG" == "" ]; then
        # In this case the entry should be added or updated
        #    if clause deals with updating an existing entry
        #    END clause deals with adding a new entry
        awk  -v hostname="$HOST_NAME" -v ip="$IP_ADDRESS" 'BEGIN { found = 0} 
        { 
            if ($2 == hostname) { 
                 print ip"  "hostname
                 found = 1
            } else { 
                 print $0 
            } 
        } 
        END { 
             if (found == 0) { 
                  print ip" "hostname
             } 
        }' /etc/hosts > /etc/temp_hosts

else
        # Delete an existing entry
        awk -v hostname="$HOST_NAME" '$2!=hostname' /etc/hosts > /etc/temp_hosts
fi

#2


0  

You should put the awk scripts inside single quotes and use variable passing to get the shell variables into the awk script. Then you won't have to do all that escaping. And I don't think the line-continuation backslashes and semicolons are necessary.

您应该将awk脚本放在单引号中并使用变量传递将shell变量放入awk脚本中。然后你不必做所有逃脱。我认为线条延续反斜杠和分号是不必要的。

Are the field separators spaces or are they spaces inside square brackets?

字段分隔符是空格还是方括号内的空格?

awk -F ' ' -v awkvar=$shellvar '
    BEGIN {
        do_something
    }
    {
        do_something_with awkvar
    }' file > out_file

Also, there's a slight danger that your tests will fail if the variable contains a string starting with a dash. There are at least a couple of ways to protect against this:

此外,如果变量包含以短划线开头的字符串,那么测试将会失败。至少有几种方法可以防止这种情况:

if [ "" == "$DELETE_FLAG" ]; then    # the dash isn't the first thing that `test` sees
if [ x"$DELETE_FLAG" == x"" ]; then  # ditto