从 ~/.ssh/config 打印别名——带或不带尾随连字符
Printing alias from ~/.ssh/config— with or without trailing hyphen
我有以下文件,它是 ssh 的配置文件。
Host vps2 # Linode
HostName xxx.xx.xx.xxx
User foo_user
Host vps3 # Vultr
HostName xxx.xx.xx.xxx
User foo_user
Host vps4
HostName xxx.xx.xx.xxx
User foo_user
Host vps5
HostName xxx.xx.xx.xxx
User foo_user
Host vps6
HostName xxx.xx.xx.xxx
User foo_user
Host vps7 # DigitalOcean
HostName xxx.xx.xx.xxx
User foo_user
Host vps8 # GCP
HostName xxx.xx.xx.xxx
User foo_user
Host pi
HostName xxx.xx.xx.xxx
User pi
# OLD SHALL NOT BE USED
Host vps13
HostName xxx.xx.xx.xxx
User foo_user
Host vps14-old
HostName xxx.xx.xx.xxx
User foo_user
Host vps4-old
HostName xxx.xx.xx.xxx
User foo_user
Host vps15-old
HostName xxx.xx.xx.xxx
User foo_user
Host vps11-old
HostName xxx.xx.xx.xxx
User foo_user
我需要打印以 vps*
开头的别名,下面(复制的)片段将完全做到这一点。
$ awk '{for(i=1;i<=NF;i++){if($i~/^vps/){print $i}}}' $HOME/.ssh/config
vps2
vps3
vps4
vps5
vps6
vps7
vps8
vps3-old
vps4-old
vps5-old
vps11-old
现在我想打印所有没有 -old
后缀的别名,添加 | grep -v old
有效。
$ awk '{for(i=1;i<=NF;i++){if($i~/^vps/){print $i}}}' $HOME/.ssh/config | grep -v "old"
vps2
vps3
vps4
vps5
vps6
vps7
vps8
有没有更干净的方法?最好只涉及 1 个工具,我尝试使用 awk
命令无济于事。
您可以使用 sed
,如果您使用支持比 grep
更扩展的正则表达式的 -n
(无打印),它具有类似 grep 的模式。可以在此处找到过滤掉以 -old
结尾的行的技巧:Sed regex and substring negation:
sed -n "/-old/b; s/^Host\s\+\(vps\S*\)\s*\(#.*\)\?//p" $HOME/.ssh/config
反向(包括-old
)稍微简单一些,因为它只需要正匹配:
sed -n "s/^Host\s\+\(vps\S*-old\)\s*\(#.*\)\?//p" $HOME/.ssh/config
您可以向 awk
命令添加 $i!~/-old$/
条件:
awk '{for(i=1;i<=NF;i++){if($i~/^vps/ && $i!~/-old$/){print $i}}}' ~/.ssh/config
(注意:当它不在双引号中时,我更喜欢 ~
而不是 $HOME
,以防路径中出现奇怪的字符。)
grep -Po '(?<=Host )vps\d+(?!-old)' file | sort -uV
这可能适合您 (GNU sed):
sed -En '/-old/!s/^Host\s*(vps\S*).*//p' file
使用 -n
和 -E
选项关闭隐式打印和扩展正则表达式。
如果一行不包含 -old
,则匹配以 Host
开头的行,后跟一些空格,然后是 vps
,然后是零个或多个非空格,然后是任何东西并将其替换为 vps
后跟任何非空白并打印结果。
要仅显示其中包含 -old
的行,请使用:
sed -En '/-old/s/^Host\s*(vps\S*).*//p' file
N.B。这依赖于 Host
行不包含注释或多个主机名。
当你想要的字符串总是在以 Host
:
开头的行的第二个字段中时,你为什么要循环?
$ awk '/^Host vps/ && !/-old/{ print }' file
vps2
vps3
vps4
vps5
vps6
vps7
vps8
vps13
我在评论中看到您实际上希望输出全部在 1 行上,即:
$ awk '/^Host vps/ && !/-old/{ printf "%s%s", sep, ; sep=OFS } END{print ""}' file
vps2 vps3 vps4 vps5 vps6 vps7 vps8 vps13
我有以下文件,它是 ssh 的配置文件。
Host vps2 # Linode
HostName xxx.xx.xx.xxx
User foo_user
Host vps3 # Vultr
HostName xxx.xx.xx.xxx
User foo_user
Host vps4
HostName xxx.xx.xx.xxx
User foo_user
Host vps5
HostName xxx.xx.xx.xxx
User foo_user
Host vps6
HostName xxx.xx.xx.xxx
User foo_user
Host vps7 # DigitalOcean
HostName xxx.xx.xx.xxx
User foo_user
Host vps8 # GCP
HostName xxx.xx.xx.xxx
User foo_user
Host pi
HostName xxx.xx.xx.xxx
User pi
# OLD SHALL NOT BE USED
Host vps13
HostName xxx.xx.xx.xxx
User foo_user
Host vps14-old
HostName xxx.xx.xx.xxx
User foo_user
Host vps4-old
HostName xxx.xx.xx.xxx
User foo_user
Host vps15-old
HostName xxx.xx.xx.xxx
User foo_user
Host vps11-old
HostName xxx.xx.xx.xxx
User foo_user
我需要打印以 vps*
开头的别名,下面(复制的)片段将完全做到这一点。
$ awk '{for(i=1;i<=NF;i++){if($i~/^vps/){print $i}}}' $HOME/.ssh/config
vps2
vps3
vps4
vps5
vps6
vps7
vps8
vps3-old
vps4-old
vps5-old
vps11-old
现在我想打印所有没有 -old
后缀的别名,添加 | grep -v old
有效。
$ awk '{for(i=1;i<=NF;i++){if($i~/^vps/){print $i}}}' $HOME/.ssh/config | grep -v "old"
vps2
vps3
vps4
vps5
vps6
vps7
vps8
有没有更干净的方法?最好只涉及 1 个工具,我尝试使用 awk
命令无济于事。
您可以使用 sed
,如果您使用支持比 grep
更扩展的正则表达式的 -n
(无打印),它具有类似 grep 的模式。可以在此处找到过滤掉以 -old
结尾的行的技巧:Sed regex and substring negation:
sed -n "/-old/b; s/^Host\s\+\(vps\S*\)\s*\(#.*\)\?//p" $HOME/.ssh/config
反向(包括-old
)稍微简单一些,因为它只需要正匹配:
sed -n "s/^Host\s\+\(vps\S*-old\)\s*\(#.*\)\?//p" $HOME/.ssh/config
您可以向 awk
命令添加 $i!~/-old$/
条件:
awk '{for(i=1;i<=NF;i++){if($i~/^vps/ && $i!~/-old$/){print $i}}}' ~/.ssh/config
(注意:当它不在双引号中时,我更喜欢 ~
而不是 $HOME
,以防路径中出现奇怪的字符。)
grep -Po '(?<=Host )vps\d+(?!-old)' file | sort -uV
这可能适合您 (GNU sed):
sed -En '/-old/!s/^Host\s*(vps\S*).*//p' file
使用 -n
和 -E
选项关闭隐式打印和扩展正则表达式。
如果一行不包含 -old
,则匹配以 Host
开头的行,后跟一些空格,然后是 vps
,然后是零个或多个非空格,然后是任何东西并将其替换为 vps
后跟任何非空白并打印结果。
要仅显示其中包含 -old
的行,请使用:
sed -En '/-old/s/^Host\s*(vps\S*).*//p' file
N.B。这依赖于 Host
行不包含注释或多个主机名。
当你想要的字符串总是在以 Host
:
$ awk '/^Host vps/ && !/-old/{ print }' file
vps2
vps3
vps4
vps5
vps6
vps7
vps8
vps13
我在评论中看到您实际上希望输出全部在 1 行上,即:
$ awk '/^Host vps/ && !/-old/{ printf "%s%s", sep, ; sep=OFS } END{print ""}' file
vps2 vps3 vps4 vps5 vps6 vps7 vps8 vps13