Shell 脚本因 grep 而中断
Shell script breaks with grep
抱歉,如果这是一个 basic/stupid 问题。
我没有 shell 脚本编写经验,但很想学习和开发。
我想创建一个脚本来读取文件,从一行中提取 IP 地址,从另一行中提取端口号并将它们都发送到一个变量以便我可以远程登录。
我的文件看起来有点像这样;
Server_1_ip=192.168.1.1
Server_2_ip=192.168.1.2
Server_port=7777
我只想获取server_1的IP
还有端口。
我现在拥有的是;
Cat file.txt | while read line; do
my_ip="(grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' <<< "$line")"
echo "$my_ip"
done < file.txt
这有效,但我如何指定 server_1_ip
?
接下来我做了同样的事情来找到端口,但不知何故端口没有显示,而是显示“server_port”而不是它后面的数字
我需要 cat 两次还是可以合并搜索?为什么它将 IP 传递给变量而不是端口?
非常感谢您的任何意见。
Awk 可能更适合:
awk -F"=" '=="Server_1_ip"{sip=}=="Server_port"{sport=}END{print sip, sport}' yourfile
这个 awk 说:
- 将每行分成由等号分隔的列:
-F"="
- 如果第一列有字符串
"Server_1_ip"
然后将第二列中的值存储到 awk 变量 sip
: =="Server_1_ip"{sip=}
- 如果第一列为字符串
"Server_port"
则将第二列的值存入awk变量sport
:=="Server_port"{sport=}
- 处理完整个文件后,打印出两个变量中的值:
END{print sip, sport}
你可以这样做:
#!/bin/bash
while IFS='=' read key value; do
case "$key" in
Server_1_ip) target_ip="$value";;
Server_port) target_port="$value";;
esac
done < input
这几乎可以肯定不是合适的解决方案,因为它要求您静态定义字符串 Server_1_ip
,但您并不完全清楚您要做什么.你可以 eval
线条,但那是有风险的。
您希望如何准确地确定要匹配的主机名将极大地影响所需的解决方案。也许你只是想要这样的东西:
#!/bin/bash
target_host="${1-Server_1_ip}"
while IFS='=' read key value; do
case "$key" in
$target_host) target_ip="$value";;
Server_port) target_port="$value";;
esac
done < input
这是一个 sed
变体:
sed -n -e'/Server_1_ip=\(.*\)/{s///;h}; /Server_port=\([0-9]*\)/{s// /;H;g;s/\n//p;q}' inputfile
-n
停止正常输出,
- 申请
-e commands
- 首先找到目标服务器,即。
Server_1_ip=
带有一个记住该值的子表达式(假设其格式正确的 IPv4)。应用一个命令块,用保存的子表达式替换模式 space(又名当前行),然后将模式 space 复制到保持缓冲区;结束命令方块。
- 继续寻找港口线路。应用删除前缀的命令块,留下端口号; 附加 端口到保持缓冲区(所以现在你有
IP newline port
处于保持状态);将保持缓冲区复制回模式 space;删除换行符并打印结果;退出。
注意:GNU 和 BSD sed
可能会有所不同,尤其是在尝试加入行时,即。 s/\n//
.
抱歉,如果这是一个 basic/stupid 问题。 我没有 shell 脚本编写经验,但很想学习和开发。
我想创建一个脚本来读取文件,从一行中提取 IP 地址,从另一行中提取端口号并将它们都发送到一个变量以便我可以远程登录。
我的文件看起来有点像这样;
Server_1_ip=192.168.1.1
Server_2_ip=192.168.1.2
Server_port=7777
我只想获取server_1的IP 还有端口。
我现在拥有的是;
Cat file.txt | while read line; do
my_ip="(grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' <<< "$line")"
echo "$my_ip"
done < file.txt
这有效,但我如何指定 server_1_ip
?
接下来我做了同样的事情来找到端口,但不知何故端口没有显示,而是显示“server_port”而不是它后面的数字
我需要 cat 两次还是可以合并搜索?为什么它将 IP 传递给变量而不是端口?
非常感谢您的任何意见。
Awk 可能更适合:
awk -F"=" '=="Server_1_ip"{sip=}=="Server_port"{sport=}END{print sip, sport}' yourfile
这个 awk 说:
- 将每行分成由等号分隔的列:
-F"="
- 如果第一列有字符串
"Server_1_ip"
然后将第二列中的值存储到 awk 变量sip
:=="Server_1_ip"{sip=}
- 如果第一列为字符串
"Server_port"
则将第二列的值存入awk变量sport
:=="Server_port"{sport=}
- 处理完整个文件后,打印出两个变量中的值:
END{print sip, sport}
你可以这样做:
#!/bin/bash
while IFS='=' read key value; do
case "$key" in
Server_1_ip) target_ip="$value";;
Server_port) target_port="$value";;
esac
done < input
这几乎可以肯定不是合适的解决方案,因为它要求您静态定义字符串 Server_1_ip
,但您并不完全清楚您要做什么.你可以 eval
线条,但那是有风险的。
您希望如何准确地确定要匹配的主机名将极大地影响所需的解决方案。也许你只是想要这样的东西:
#!/bin/bash
target_host="${1-Server_1_ip}"
while IFS='=' read key value; do
case "$key" in
$target_host) target_ip="$value";;
Server_port) target_port="$value";;
esac
done < input
这是一个 sed
变体:
sed -n -e'/Server_1_ip=\(.*\)/{s///;h}; /Server_port=\([0-9]*\)/{s// /;H;g;s/\n//p;q}' inputfile
-n
停止正常输出,- 申请
-e commands
- 首先找到目标服务器,即。
Server_1_ip=
带有一个记住该值的子表达式(假设其格式正确的 IPv4)。应用一个命令块,用保存的子表达式替换模式 space(又名当前行),然后将模式 space 复制到保持缓冲区;结束命令方块。 - 继续寻找港口线路。应用删除前缀的命令块,留下端口号; 附加 端口到保持缓冲区(所以现在你有
IP newline port
处于保持状态);将保持缓冲区复制回模式 space;删除换行符并打印结果;退出。
- 首先找到目标服务器,即。
注意:GNU 和 BSD sed
可能会有所不同,尤其是在尝试加入行时,即。 s/\n//
.