BASH:如何仅抓取由多个 space 分隔的列?
BASH: How do I grab columns that are separated by more than one space only?
我试图从 protonvpn s
的输出中获取 select 值,但我无法获得正确的值,因为某些单词之间有 space。如果 多个 连续 space,我只想拆分值。我也只对接收第二列中的值感兴趣。
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 }' ) ; 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 }' ) ; echo "$vpn"
会产生:
Connected
0:42:02
162.253.71.24
CH-CA#1
Secure-Core
TCP
Switch:
United
None
34%
4.75
1.32
我还尝试用破折号 (-)
替换单个 spaces ' '
由:
vpn=$(protonvpn s)
vpn_parsed=${vpn// /-}
echo "$vpn_parsed"
但它会替换所有 space,而不是单词之间的单个 space:
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 }'
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
)之间的单个 space,但我确实需要删除第一列和额外的白色 space。
知道我需要这个输出在一个数组中,由每行分隔,而不是 space。这样我就可以提取值,比如国家,像这样:
echo ${vpn_arr[7]
// Outputs "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
使用 cat file
代替我没有的 protonvpn s
:
$ declare -A arr="( $(cat file | awk '{tag=val=[=10=]; sub(/:.*/,"",tag); sub(/[^:]+:[[:space:]]*/,"",val); printf " [7%s7]=7%s7", 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
vpn=$(protonvpn s | sed 's/^.*: *//' ) ; echo "$vpn"
应该可以解决问题,它会替换 (s/) 从行首 (^.*) 开始的所有内容,包括“:”之后的任意数量的空格 (*),没有任何内容 (//)。
使用 sed
您可以删除每行的开头,直到遇到 :
加上以下 space 个字符:
protonvpn s | sed 's/^[^:]*: *//'
s/
替换
^
匹配行首
[^:]*
匹配任何非:
字符
:
匹配文字 :
*
匹配任何 space 个字符
//
什么都不替换
要将输出存储到数组中,您可以使用 mapfile
:
$ mapfile -t vpn_arr <<< $(protonvpn s | sed 's/^[^:]*: *//')
$ echo "${vpn_arr[7]}"
United States
你可以使用cut
命令:
vpn=$(protonvpn s | cut -d':' -f 2,3,4)
cut
命令通过指定的分隔符(-d 选项)切割字符串,-f 选项指定要return 的子字符串。由于 protonvpn s
输出的第二行是 Time: 0:34:07
我们需要将 -f 选项设置为 2,3,4 以吞噬所有部分。
我试图从 protonvpn s
的输出中获取 select 值,但我无法获得正确的值,因为某些单词之间有 space。如果 多个 连续 space,我只想拆分值。我也只对接收第二列中的值感兴趣。
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 }' ) ; 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 }' ) ; echo "$vpn"
会产生:
Connected
0:42:02
162.253.71.24
CH-CA#1
Secure-Core
TCP
Switch:
United
None
34%
4.75
1.32
我还尝试用破折号 (-)
替换单个 spaces ' '
由:
vpn=$(protonvpn s)
vpn_parsed=${vpn// /-}
echo "$vpn_parsed"
但它会替换所有 space,而不是单词之间的单个 space:
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 }'
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
)之间的单个 space,但我确实需要删除第一列和额外的白色 space。
知道我需要这个输出在一个数组中,由每行分隔,而不是 space。这样我就可以提取值,比如国家,像这样:
echo ${vpn_arr[7]
// Outputs "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
使用 cat file
代替我没有的 protonvpn s
:
$ declare -A arr="( $(cat file | awk '{tag=val=[=10=]; sub(/:.*/,"",tag); sub(/[^:]+:[[:space:]]*/,"",val); printf " [7%s7]=7%s7", 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
vpn=$(protonvpn s | sed 's/^.*: *//' ) ; echo "$vpn"
应该可以解决问题,它会替换 (s/) 从行首 (^.*) 开始的所有内容,包括“:”之后的任意数量的空格 (*),没有任何内容 (//)。
使用 sed
您可以删除每行的开头,直到遇到 :
加上以下 space 个字符:
protonvpn s | sed 's/^[^:]*: *//'
s/
替换^
匹配行首[^:]*
匹配任何非:
字符:
匹配文字:
*
匹配任何 space 个字符//
什么都不替换
要将输出存储到数组中,您可以使用 mapfile
:
$ mapfile -t vpn_arr <<< $(protonvpn s | sed 's/^[^:]*: *//')
$ echo "${vpn_arr[7]}"
United States
你可以使用cut
命令:
vpn=$(protonvpn s | cut -d':' -f 2,3,4)
cut
命令通过指定的分隔符(-d 选项)切割字符串,-f 选项指定要return 的子字符串。由于 protonvpn s
输出的第二行是 Time: 0:34:07
我们需要将 -f 选项设置为 2,3,4 以吞噬所有部分。