BASH:如何获取仅由多个空格分隔的列?

问题描述

我正在尝试从protonvpn s输出获取选择值,但是由于某些词之间有空格,因此我无法获得正确的值。我只想在连续多个 个空格时拆分值。我也只想在第二栏中接收值。

protonvpn s产生(例如)

输出
Status:       Connected
Time:         0:34:07
IP:           888.888.888.888
Server:       CH-CA#1
Features:     Secure-Core
Protocol:     TCP
Kill Switch:  Enabled
Country:      United States
City:         None
Load:         34%
Received:     4.43 MB
Sent:         1.17 MB

如果我尝试vpn=$(protonvpn s | column -s '\t' -t | awk '{print $2}' ) ; echo "$vpn" 产生:

a
0:27:57
162.253.71.24
CH-CA#1
ures:
ocol:
Swi
ry:
y:
29%
3.33
:

如果我尝试 vpn=$(protonvpn s | column -s ' ' -t | awk '{print $2}' ) ; echo "$vpn"会产生:

Connected
0:42:02
162.253.71.24
CH-CA#1
Secure-Core
TCP
Switch:
United
None
34%
4.75
1.32

我也尝试用破折号' '替换单个空格(-)方法是:

vpn=$(protonvpn s)
vpn_parsed=${vpn// /-}
echo "$vpn_parsed"

但是它将替换所有空格,而不是单词之间的单个空格:

Status:-------Connected
Time:---------0:47:47
IP:-----------162.253.71.24
Server:-------CH-CA#1
Features:-----Secure-Core
Protocol:-----TCP
Kill-Switch:--Enabled
Country:------United-States
City:---------None
Load:---------34%
Received:-----4.92-MB
Sent:---------1.42-MB

然后我似乎无法用破折号作为分隔符来捕获任何列:

vpn_out="$vpn_parsed" | column -s '-' -t | awk '{print $2}'
echo "$vpn_out"

// Produces no output

我希望并希望输出为:

Connected
0:34:07
888.888.888.888
CH-CA#1
Secure-Core
TCP
Enabled
United States
None
34%
4.43 MB
1.17 MB

有人可以帮我解决这个问题吗?我不是一个非常高级的Bash用户,我似乎根本无法使它正常工作。我不反对用破折号或其他字符替换单词之间的空格(例如United States),但我确实需要删除第一列和多余的空格。

知道我将需要在数组中的此输出也可能是相关的,该数组以每行而不是空格分隔。这样,我就可以像这样提取价值,例如国家/地区:

echo ${vpn_arr[7]

// Outputs "United States"

解决方法

使用cat file代替我没有的protonvpn s

$ declare -A arr="( $(cat file | awk '{tag=val=$0; sub(/:.*/,"",tag); sub(/[^:]+:[[:space:]]*/,val); printf " [\047%s\047]=\047%s\047",tag,val}') )"

$ declare -p arr
declare -A arr=([Sent]="1.17 MB" [Features]="Secure-Core" [Country]="United States" ["Kill Switch"]="Enabled" [Server]="CH-CA#1" [Load]="34%" [Received]="4.43 MB" [IP]="888.888.888.888" [Protocol]="TCP" [Time]="0:34:07" [City]="None" [Status]="Connected" )

$ for i in "${!arr[@]}"; do echo "$i --> ${arr[$i]}"; done
Sent --> 1.17 MB
Features --> Secure-Core
Country --> United States
Kill Switch --> Enabled
Server --> CH-CA#1
Load --> 34%
Received --> 4.43 MB
IP --> 888.888.888.888
Protocol --> TCP
Time --> 0:34:07
City --> None
Status --> Connected

$ echo "${arr[Country]}"
United States

$ echo "${arr[Received]}"
4.43 MB

$ echo "${arr[Kill Switch]}"
Enabled
,
  num       value      category      name             output
  503       8978       bird          woodpecker       
  502       7812       animal                         panther
  502       7812       animal                         panther
  501       7812       animal                         panther
  500       7812       animal        panther          panther
  499       7812       animal                         panther
  498       7812       animal                         panther
  467       7812       animal        elephant         elephant 

应该做到这一点,它将替换行(^。*)开头的所有内容(s /),包括在':'之后不加任何空格(* /)的空格(*)。

,

使用sed,您可以删除每行的开头,直到遇到:以及以下空格字符为止:

protonvpn s | sed 's/^[^:]*: *//'
  • s/替代人
  • ^匹配行的开头
  • [^:]*匹配所有非:字符
  • :与文字:匹配
  • *匹配任何空格字符
  • //替换为空

要将输出存储到数组中,可以使用mapfile

$ mapfile -t vpn_arr <<< $(protonvpn s | sed 's/^[^:]*: *//')
$ echo "${vpn_arr[7]}"
United States
,

您可以使用sed代替awk:

protonvpn s | sed -r 's/\S+\s*//'

这个想法是删除所有字符,直到第一个空格,然后再删除空格。

\S+     # Any non-whitespace character,repeated one or more
\s*     # Any white-space character,repeated one or more
,

您可以使用cut命令:

vpn=$(protonvpn s | cut -d':' -f 2,3,4)

cut命令使用指定的定界符(-d选项)剪切字符串,-f选项指定要返回的子字符串。由于protonvpn s输出的第二行是Time: 0:34:07,我们需要将-f选项设置为2,4以便吞噬所有部分。