使用 AWK 和 gsub 查找/替换配置文件中的设置

问题描述 投票:0回答:1

我正在尝试做一些应该简单而常规的事情。 我想搜索文件 /etc/dhcpcd.conf 并更改分配给 eth0 的未注释的静态 IP 地址。示例测试文件显示在这里:

interface eth0
# test variants of comments
#static ip_address=192.168.21.40/24
# static ip_address=192.168.21.40/24
 #static ip_address=192.168.21.40/24
 # static ip_address=192.168.21.40/24

#the line to match and change
static ip_address=123.223.122.005/24

我试图在这里实施一个解决方案: 这是在 awk 中做这件事的一种不那么神秘的方式 由 Scott 回答 - Слава Україні

我选择 AWK 解决方案是因为它易于阅读,但是我无法修改适合我的答案。我之前没有用过

sed
awk
所以我写了一个测试脚本。

#!/bin/bash
# testing on a copy of the config file
conf_file="/home/user/dhcpcd.conf"
# BASH variable with fake test ip
new_ip=111.222.123.234

cat "$conf_file" |  awk $'
   /interface /                    { matched=0 }
   /interface eth0/                { matched=1 }
    matched                        { gsub( "^\\s*static ip_address=•*" , "static ip_address=111.222.123.234" ) }
                                   { print }
   '

这个AWK脚本是找到

eth0
节,然后找到
static ip_address=
任何文本。 并将其替换为
static ip_address=111.222.123.234
#
注释行除外。为了进行测试,我已将测试新 ip 硬编码到 AWK 脚本中。我想使用变量 $new_ip.

最初 gsub 函数有问题。

•*
旨在匹配任何导致问题的文本,因为我开始使用
.*
。手册说 gsub 使用字符
而不是句号
.
而没有真正强调使用
Alt-7
的必要性。我花了一段时间才找到,但现在这个问题已经解决了。

我现在剩下的第一个问题是新的 ip 被插入到行中而不是替换旧的 ip。输出是:

 static ip_address=111.222.123.234123.223.122.005/24
所以正则表达式是,或者应该是,匹配整行,包括要替换的旧 ip,但它不是。

我遇到的第二个问题是我需要

awk
来使用bash变量
new_ip
。我已经看过并搜索过,但找不到有效的答案。

我认为这应该有效:

cat /home/mimir/dhcpcd.conf |  awk -v sip=$new_ip  $'
   /interface /                    { matched=0 }
   /interface eth0/                { matched=1 }
    matched                        { gsub( "^[:blank:]*static ip_address=•*" , "static ip_address=sip" ) }
                                   { print }

 '

但事实并非如此。输出是

static ip_address=sip123.223.122.005/24
所以 awk 没有将
sip
识别为变量。我做错了什么,但我看不到。做这么简单的事情应该不难吧

任何帮助将不胜感激。

编辑 2 号: 为了那些登陆这里寻找解决方案的人的利益,这是我的工作测试脚本:

 #!/bin/bash
#  Test reading and setting of the ip address in /etc/dhcpcd.conf  using AWK

# source /etc/dhcpcd.conf  which always includes the lines:
# interface eth0
#  static ip_address=www.xxx.yyy.zzz
# copy of config file for testing
cfg_file="/home/user/dhcpcd.conf"
# fake test ip
new_ip="114.113.112.111"

awk -i inplace -v sip=$new_ip  $'
   /interface /                    { matched=0 }
   /interface eth0/                { matched=1 }
    matched                        { gsub( "^[[:blank:]]*static ip_address=.*" , "static ip_address="sip ) }
                                   { print }
   ' $cfg_file
exit

由于下面评论中收到的建议组合,现在可以正常工作。这是一个答案,但这不是我的答案。它有效但并不完美。

bash awk gsub
1个回答
3
投票

使用任何 POSIX awk:

$ cat tst.sh
#!/usr/bin/env bash

new_ip=111.222.123.234

awk -v sip="$new_ip" '
    $1 == "interface" {
        gotIface = ($2 == "eth0" ? 1 : 0)
    }
    gotIface && match($0,/^[[:space:]]*static[[:space:]]+ip_address=/) {
        $0 = substr($0,1,RSTART+RLENGTH) sip
    }
    { print }
' file

$ ./tst.sh
interface eth0
# test variants of comments
#static ip_address=192.168.21.40/24
# static ip_address=192.168.21.40/24
 #static ip_address=192.168.21.40/24
 # static ip_address=192.168.21.40/24

#the line to match and change
static ip_address=1111.222.123.234

关于:

需要读写同一个文件

GNU awk 有

-i inplace
(但它仍在幕后使用临时文件),但对于任何 Unix 工具,
tool
,你可以这样做:

tmp=$(mktemp) &&
tool file > "$tmp" &&
mv -- "$tmp" file

例如

tmp=$(mktemp) &&
awk '{print FILENAME, $0}' file > "$tmp" &&
mv -- "$tmp" file

将在每个输入行前加上文件名并将结果写回输入文件。

© www.soinside.com 2019 - 2024. All rights reserved.