捕获 bash 命令的输出,解析它并存储到不同的 bash 变量中

捕获 bash 命令的输出,解析它并存储到不同的 bash 变量中

解释:

我有一个小巴什只需运行的脚本任何Linux 命令(例如说ifconfig

典型输出为如果配置是这样的:

eth0      Link encap:Ethernet  HWaddr 30:F7:0D:6D:34:CA
          inet addr:10.106.145.12  Bcast:10.106.145.255  Mask:255.255.255.0
          inet6 addr: fe80::32f7:dff:fe6d:34ca/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1104666 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2171 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:444437904 (423.8 MiB)  TX bytes:238380 (232.7 KiB)

lo        Link encap:Local Loopback 
          inet addr:127.0.0.1  Mask:255.255.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:15900 errors:0 dropped:0 overruns:0 frame:0
          TX packets:15900 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:467306 (456.3 KiB)  TX bytes:467306 (456.3 KiB)

现在大多数人通常做的就是存储全部的输出到文件/变量并基于此进行解析。然而我想知道是否有什么可以放的具体的输出的一部分包含在多个变量中(例如bash 变量被调用${IPETH0}以携带 IP10.106.145.12地址以太网0${IPLO}携带 IP127.0.0.1地址在上面的例子中无需运行 ifconfig 命令两次)。

就好像是球座命令对输入进行处理,但我想为输出并将输出存储到2或更多的变量一气呵成。有任何想法吗?

答案1

得到了答案:

$ read IPETH0 IPLO <<< $(ifconfig | awk '/inet[[:space:]]/ { print $2 }' | cut -d ':' -f 2)
$ echo "${IPETH0}"
192.168.23.2
$ echo "${IPLO}"
127.0.0.1

eth0这假定了和接口的顺序lo,但它显示了基本思想。

纯的awk

您可以专门awk使用该split函数来执行此操作:

$ read IPETH0 IPLO <<< $(ifconfig | awk '/inet[[:space:]]/ { split($2,a,":"); print a[2]}')

答案2

我假设您知道每个命令要存储命令返回的哪一部分。

在您的示例中,这将是单词 7 和 47。

这样做(注意命令周围的反勾号ifconfig):

array=(`ifconfig`)

显示该数组的所有元素:

echo ${array[@]}
eth0 Link encap:Ethernet HWaddr 30:F7:0D:6D:34:CA inet addr:10.106.145.12 Bcast:10.106.145.255 Mask:255.255.255.0 inet6 addr: fe80::32f7:dff:fe6d:34ca/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1104666 errors:0 dropped:0 overruns:0 frame:0 TX packets:2171 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:444437904 (423.8 MiB) TX bytes:238380 (232.7 KiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.255.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:15900 errors:0 dropped:0 overruns:0 frame:0 TX packets:15900 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:467306 (456.3 KiB) TX bytes:467306 (456.3 KiB)

显示具体词:

echo ${array[6]} ${array[46]}
addr:10.106.145.12 addr:127.0.0.1

将结果通过管道传输到 sed 中以仅提取您的 IP 地址:

echo ${array[6]} ${array[46]} | sed 's/addr://g'
10.106.145.12 127.0.0.1

使用 Arpith 的巧妙方法和“阅读”在这里是灵活的答案。

read IPETH0 IPLO <<< $(echo ${array[6]} ${array[46]} |\
sed 's/addr://g')
echo $IPETH0 $IPLO
10.106.145.12 127.0.0.1

请注意,数组元素是从 0 开始计数的。因此,您的单词编号 7 将被称为“${array[6]}”。

数组索引是正整数。因此,您可以在 shell 脚本中进行各种计算来选择特定的单词(例如范围或 for 循环)...

要编写可移植脚本,您需要保留一种包含这些数字的表格。在我的系统 (BSD) 上,IP 地址将是数字 17 和 49,而不是 Linux 数字 7 和 47。而且生成的字符串看起来不同(忽略我的本地和 Arpith 的全局 ID 地址):

echo ${array2[16]}
192.168.0.103

echo ${array2[48]}
127.0.0.1

slm 的“纯 awk”方法(见下文)在我的 BSD 系统上会失败。将函数拆分为数组将不起作用,因为我的“ifconfig”命令打印“127.0.0.1”和 Arpith 的“addr:127.0.0.1”...

read IPETH0 IPLO <<< $(ifconfig |\
 awk '/inet[[:space:]]/ { split($2,a,":"); print a[2]}')

华泰

伯尼

答案3

执行此操作的常用方法是awk生成一些bash代码并由bash.

喜欢:

eval "$(
  ifconfig | awk -F '[: ]+' '
    /^[^[:blank:]]/ {iface=$1}
    /inet addr:/ {ip[iface]=$4}
    END {for (i in ip) print "IP" toupper(i) "=" ip[i]}')"

答案4

AWK:

/sbin/ifconfig | awk -F':' 'NR==2{split($2,a," "); print a[1]}'

SED:

ip -f inet addr show dev eth0 | sed -n 's/^ *inet *\([.0-9]*\).*/\1/p'

或者

ifconfig eth0 | sed -n 's/^ *inet addr:*\([.0-9]*\).*/\1/p'

GREP:

ifconfig eth0|grep -Po 't addr:\K[\d.]+'

感谢@Stephane Chazelas

相关内容