7
\$\begingroup\$

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 (.+)/) {
 $_=1ドル;
 foreach $i(/([^ ]+)/g) {
 $h{$i}=1
 }
 }
}
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 
200_success
146k22 gold badges191 silver badges481 bronze badges
asked Jan 28, 2019 at 19:27
\$\endgroup\$

1 Answer 1

7
\$\begingroup\$

I would use something like

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

or

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
answered Jan 28, 2019 at 20:01
\$\endgroup\$
2
  • 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\$ Commented 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\$ Commented Jan 31, 2019 at 13:21

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.