问题
I am using this awk code to pick out an IP address in the /etc/hosts file and although I can force it to match the correct hostname, awk will select an "almost like" hostname if it see's it first. I have researched this and I cannot figure it out.
sUSER=machine_005
ip=$(awk '/^[[:space:]]*($|#)/{next}/'$sUSER'/{print $1; exit}' /etc/hosts)
I know the first part looks for $ or # and if found calls the next line. This feature is needed in the final formula. The other feature needed is to stop after the first match. I know that the next /xxx/ searches for the pattern and if found prints $1 to $ip.
Here is a sample of my hosts file
555.555.555.555 machine.005
222.222.222.222 machine_005
if I $sUSER=machine_005
$ip
is 222.222.222.222
just like you'd expect.
if I $sUSER=machine.005
$ip
is 555.555.555.555
just like you'd expect
But if my /etc/hosts is:
222.222.222.222 machine_005
555.555.555.555 machine.005
Then if I $sUSER=machine_005
$ip
is 222.222.222.222
just like you'd expect.
However, if I $sUSER=machine.005
$ip
is 222.222.222.222
It takes machine_005
ip address.
Could this be a bug? or is this on purpose?
Thanks.
Hello. I wanted to post my final line of code that provides the correct output. I appreciate all of the help and guidance from those who responded. I wanted to post the final code in case someone in the future can find it useful.
ip=$(awk -v sUSER=$sUSER 'BEGIN{gsub(/\./,"\\.",sUSER)}match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) && $0 ~ ("[^[:alpha:]]"sUSER"$") && $0 !~ /^$/ && $0 !~ /^#/{print $1}' /etc/hosts)
回答1:
In a regular expression, .
matches any character. You need to escape it to make it match literally.
sUser='machine\.005'
If you're getting the value from user input, you can use the shell's substitution operator:
sUser=${sUser//./\\.}
Also see How do I use shell variables in an awk script? for a better way to incorporate the shell variable into the awk
script.
回答2:
EDIT2: as per OP need to remove lines start from #
and empty lines I believe then try following.
sUser="machine.005"
ip=$(awk -v sUSER="$sUSER" 'BEGIN{sub(/\./,"\\.",sUser)} match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) && $0 ~ sUSER && $0 !~ /^$/ && $0 !~ /^#/{print $1}' /etc/hosts)
EDIT: Or to escape DOT inside awk
code itself try following.
sUser="machine.005"
awk -v sUser="$sUser" 'BEGIN{sub(/\./,"\\.",sUser)} match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) && $0 ~ sUser{print $2}' Input_file
Since DOT is considered as any character so that is why it is catching everything between machine
and 005|6
, so we need to escape it to tell program that it is an actual DOT and shouldn't be considered as special meaning.
Could you please try following.
sUser="machine\\\.005"
awk -v u="$sUser" 'match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) && $0 ~ u{print $2}' Input_file
Output will be as follows.
machine.005
回答3:
getent
is a tool meant to retrieve entries from /etc/hosts
(and other config databases):
getent hosts "${USER}" | cut -d' ' -f1
来源:https://stackoverflow.com/questions/53353494/awk-matching-incorrect-hostname-in-etc-hosts