【发布时间】:2016-07-05 22:00:12
【问题描述】:
sed 中是否有某种方法可以从单个输入行创建多个输出行?我有一个模板文件(文件里有更多的行,我只是简化它):
http://hostname:@PORT@
我目前正在使用 sed 将 @PORT@ 替换为真实端口。但是,我希望能够传入多个端口,并为每个端口创建一条线。这可能吗?
【问题讨论】:
标签: sed
sed 中是否有某种方法可以从单个输入行创建多个输出行?我有一个模板文件(文件里有更多的行,我只是简化它):
http://hostname:@PORT@
我目前正在使用 sed 将 @PORT@ 替换为真实端口。但是,我希望能够传入多个端口,并为每个端口创建一条线。这可能吗?
【问题讨论】:
标签: sed
我假设您希望为每个端口号复制整行。在这种情况下,更容易将其视为用 URL 替换端口号:
$ cat ports.in
1
2
3
4
5
$ sed 's#^\([0-9]*\$)#http://hostname:\1#' ports.in
http://hostname:1
http://hostname:2
http://hostname:3
http://hostname:4
http://hostname:5
使用awk 反过来更容易:
$ cat url.in
http://hostname:@PORT@
$ awk '/^[0-9]/ {ports[++i]=$0} /^http/ {sub(":@PORT@", ":%d\n"); for (p in ports) printf($0, ports[p])}' ports.in url.in
http://hostname:2
http://hostname:3
http://hostname:4
http://hostname:5
http://hostname:1
这会读取ports.in 和url.in,如果一行以数字开头,则假定它是来自ports.in 的端口号。否则,如果该行以http 开头,则假定它是来自url.in 的URL,并将用printf 格式化字符串替换端口占位符,然后为读取的每个端口号打印一次URL。如果文件以错误的顺序输入,它将无法做正确的事情。
类似的解决方案,但从 shell 变量中获取 URL:
$ myurl="http://hostname:@PORT@"
$ awk -v url="$myurl" 'BEGIN{sub(":@PORT@", ":%d\n",url)} /^[0-9]/ {ports[++i]=$0} END {for (p in ports) printf(url, ports[p])}' ports.in
http://hostname:2
http://hostname:3
http://hostname:4
http://hostname:5
http://hostname:1
【讨论】:
您似乎有多个模板和多个端口可应用于它们。以下是如何在 shell 脚本中执行此操作(使用 bash 测试),但如果您想保持简单,则需要在两次 sed 执行中执行此操作,因为您有两个多值输入。它在数学上是模板和替换值的叉积。
ports='80
8080
8081'
templates='http://domain1.net:%PORT/
http://domain2.org:%PORT/
http://domain3.com:%PORT/'
meta="s/(.*)/g; s|%PORT|\1|p; /p"
sed="`echo \"$ports\" |sed -rn \"$meta\" |tr '\n' ' '`"
echo "$templates" |sed -rn "h; $sed"
shell 变量 meta 是一个元 sed 脚本,因为它编写了另一个 sed 脚本。 h 将模式缓冲区保存在 sed 保持空间中。从每个端口的元 sed 调用、替换和打印生成的 sed 命令。这就是结果。
http://domain1.net:80/
http://domain1.net:8080/
http://domain1.net:8081/
http://domain2.org:80/
http://domain2.org:8080/
http://domain2.org:8081/
http://domain3.com:80/
http://domain3.com:8080/
http://domain3.com:8081/
【讨论】: