sed 命令替换配置文件中的值

sed 命令替换配置文件中的值

我正在编写自动化脚本,需要更改配置文件中的值。我尝试编辑的配置文件有这样一行(包括前面的空格):

    "peer-port": 23456,

可以23456是任何 5 位数字。我正在编写的脚本将传递一个存储在名为 的变量中的新端口$newport。如何使用sed(或awk) 命令来替换“23456”,(或无论它是什么),新的端口值包含在变量$newport?

一个比较完整的样本配置文件是:

{
    "alt-speed-down": 50, 
    "alt-speed-enabled": false, 
    "alt-speed-time-begin": 540, 
    "alt-speed-time-day": 127, 
    "alt-speed-time-enabled": false, 
    "alt-speed-time-end": 1020, 
    "alt-speed-up": 50, 
    "bind-address-ipv4": "0.0.0.0", 
    "bind-address-ipv6": "::", 
    "blocklist-enabled": false, 
    "blocklist-url": "http://www.example.com/blocklist", 
    "cache-size-mb": 2, 
    "dht-enabled": true, 
    "download-dir": "/var/media/orng/dl/", 
    "download-queue-enabled": true, 
    "download-queue-size": 1, 
    "encryption": 2, 
    "idle-seeding-limit": 30, 
    "idle-seeding-limit-enabled": false, 
    "incomplete-dir": "/var/media/orng/dl//incoming", 
    "incomplete-dir-enabled": true, 
    "lpd-enabled": false, 
    "message-level": 2, 
    "peer-congestion-algorithm": "", 
    "peer-limit-global": 100, 
    "peer-limit-per-torrent": 20, 
    "peer-port": 51413, 
    "peer-port-random-high": 65535, 
    "peer-port-random-low": 49152, 
    "peer-port-random-on-start": false, 
    "peer-socket-tos": "default", 
    "pex-enabled": true, 
    "port-forwarding-enabled": true, 
    "preallocation": 1, 
    "prefetch-enabled": 0, 
    "queue-stalled-enabled": true, 
    "queue-stalled-minutes": 30, 
    "ratio-limit": 0, 
    "ratio-limit-enabled": true, 
    "rename-partial-files": true, 
    "rpc-authentication-required": false, 
    "rpc-bind-address": "0.0.0.0", 
    "rpc-enabled": true, 
    "rpc-password": "{43041796ac49801e85577ba94a0e4ee5642d53a6soamZcAy", 
    "rpc-port": 9091, 
    "rpc-url": "/transmission/", 
    "rpc-username": "", 
    "rpc-whitelist": "127.0.0.1, 192.168.1.*", 
    "rpc-whitelist-enabled": true, 
    "scrape-paused-torrents-enabled": true, 
    "script-torrent-done-enabled": false, 
    "script-torrent-done-filename": "", 
    "seed-queue-enabled": false, 
    "seed-queue-size": 10, 
    "speed-limit-down": 100, 
    "speed-limit-down-enabled": false, 
    "speed-limit-up": 100, 
    "speed-limit-up-enabled": false, 
    "start-added-torrents": true, 
    "trash-original-torrent-files": false, 
    "umask": 18, 
    "upload-slots-per-torrent": 14, 
    "utp-enabled": true, 
    "watch-dir": "/var/media/orng/dl//watch", 
    "watch-dir-enabled": true
}

答案1

jq --argjson port "$newport" '."peer-port" |= $port' file.json >file-new.json

这将生成一个新文件,file-new.json该文件peer-port的键值将更改为 shell 变量的值$newport。 shell 变量将按原样插入,即不进行任何编码,因此请确保它是纯整数(使用--arg而不是--argjson将其作为编码字符串插入)。

答案2

试试这个测试:

sed 's/^    "peer-port": [0-9]*,/    "peer-port": '"${newport}"',/' settings.json

...检查输出,如果它看起来不错,添加一个-i来实际更改文件,如下所示:

sed -i 's/^    "peer-port": [0-9]*,/    "peer-port": '"${newport}"',/' settings.json

注释:s替代字符串可能需要一些调整,(IE将“ ”替换为“ \t”),具体取决于空格是空格还是制表符。

一种更紧凑、更高效(但可能不太便携)的方法:

sed `/^    "peer-port": /{s/ [0-9]*,/ '"${newport}",'/;q}' settings.json

答案3

一般来说,您不需要整个字符串来为 sed 搜索字符串创建模式,您只需要它的唯一部分,并且“(peer-port.+) ([0-9]+)”看起来完全足够在这种情况下,找到带有小尾巴的关键字,然后是数字序列,并将所有内容替换为第一件事不变(\1),第二件事使用脚本中的字符串。

#!/bin/bash

FNAME=$1
NPORT=$2
SSTR='{s/(peer-port.+) ([0-9]+)/\1 '$NPORT'/};'
echo "new port $NPORT in $FNAME"

sed -E -i -e "$SSTR" $FNAME

答案4

解析嵌套数据格式(如 json)必须使用相应的(json 格式感知)实用程序来完成。sed是一条只知道的线。这是一个基于 walk-path unix 实用程序的简单解决方案jtc:

bash $ newport=12345
bash $ jtc -w[peer-port] -u"$newport" -f file.json 
bash $ jtc -w[peer-port] file.json 
12345
bash $ 

相关内容