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