Shell Pipelines
I'm trying to understand this Shell line:
grep ^x06 ssh_known_hosts |
ssh-keygen -l -f -|
\sed -e 's/^.*\(SHA256:\S\+\).*(\([^)]\+\))/\2: \1/' >fp
- So with
grep
we are basically searching for the datassh_unknown_hosts
. What is^x06
used for? - With the
ssh-keygen
command we are generating a SSH key with-l
. What's the-f
used for? - The last line I didn't get.
Solution 1:
grep
is searching the file ssh_known_hosts
for the line (or lines) starting with x06
(^
indicates a beginning of line in a regular expression) and outputs it.
From man ssh-keygen
:
ssh-keygen -l [-f input_keyfile]
[...]
-l Show fingerprint of specified public key file. Private RSA1 keys
are also supported. For RSA and DSA keys ssh-keygen tries to
find the matching public key file and prints its fingerprint. If
combined with -v, an ASCII art representation of the key is sup‐
plied with the fingerprint.
So ssh-keygen -l -f -
reads key from standard input (that is, from the line that has been output by grep
) and outputs its fingerprint (-
used as a filename indicates standard input).
The sed
part is the most difficult. One needs to understand well regular expressions to understand what it does.
sed
runs the command s/pattern/replacement/
on each line of input, that is, replaces pattern
with replacement
and copies the line to standard output. If the pattern
is not found in the line, the line is copied unchanged.
The pattern
sed
is looking for is: ^.*\(SHA256:\S\+\).*(\([^)]\+\))
. It is a regular expression of course.
It can be broken down as follows:
-
beginning of line (
^
), followed by zero or more of any characters (.*
), followed by first group (the part between\( ... \)
; we get to the details later), followed by zero or more of any characters (.*
), followed by second group, which is enclosed in literal parentheses(\( ... \))
. -
The first group is
SHA256:\S\+
. This means a literal stringSHA256:
, followed by one or more non-space characters (\S\+
) - however, it should be noted that not allsed
implementations will support\S
as an indication of non-space character. So first group matchesSHA256:
followed by any characters, up to the first space. -
The second group is
[^)]\+
, that is, one or more characters that are not equal to the closing parenthesis. Taking into account that the entire group is placed in parentheses, the second group matches any string placed in parentheses, up to the closing parenthesis.
Summing up, sed
searches in line for a pattern consisting of SHA256:
plus any non-space characters, and then any string placed in parentheses, with anything between them.
The matched pattern is replaced with \2: \1
which is the text matching the second group (\2
), colon, space and the text matching the first group (\1
).
For example, if ssh-keygen
output contains a line like
begin something SHA256:123456 middle something (text inside parens) end something
sed
will replace that line with
text inside parens: SHA256:123456 end something
Lines that don't contain the pattern won't be changed.