Here is the working code (intended to be executed with perl -e '<code>' ~/.ssh/config):

Actual version:

while(<>){if(/^Host (.+)/){$_=$1;foreach $i(/([^ ]+)/g){$h{$i}=1}}}print "$_ " for keys %h;

Identical version with whitespace for reading:

while(<>) {
    if(/^Host (.+)/) {
        foreach $i(/([^ ]+)/g) {
print "$_ " for keys %h;

I'm sort of a perl newbie. Is $_=$1 kosher? Is there a straight-forward way to do this with a single regex? Is there anything else I should be doing better here?

Example input output:

For a config file with contents like this:

Host build
    HostName build.myserver.com
Host build build.myserver.com
    User ubuntu
    IdentityFile ~/.ssh/build
Host tunnel
    LocalForward 6397 redis.production.com:6379

The output should be (order is not required, trailing space is not required but acceptable):

build build.myserver.com tunnel 

1 Answer 1


I would use something like

perl -lane '@h{@F[1..$#F]}=()if/^Host\b/;END{$,=" ";print keys %h}' -- file


perl -lane '@h{ @F[ 1 .. $#F ] } = () if /^Host\b/;
            END {
                $, = " ";
                print keys %h;
            }' -- file
  • -l removes newlines from input and adds them to prints
  • -n runs the code for each line of the input
  • -a splits each line on whitespace into the @F array
  • the hash %h is populated by all the non-whitepsace strings following Host
  • at the end, all the keys are printed separated by space
  • 1
    \$\begingroup\$ Commenting some other things I learned from this answer that I didn't know previously: $#array returns the last index of an array, $, is the "output field separator" printed automatically between fields, END{} gives a block of code that is executed when exiting, useful for doing final one-time code while still using the -n option. \$\endgroup\$ Jan 28, 2019 at 20:22
  • \$\begingroup\$ can shave a few characters there by switching to print "@{[ EXPR ]}" and using eof in place of an END block. And the spaces after -e and keys are optional. perl -lane'@h{@F[1..$#F]}=()if/^Host\b/;eof&&print"@{[keys%h]}"' -- file \$\endgroup\$ Jan 31, 2019 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.