如何操作字符串并以零开头

时间:2018-07-15 20:47:13

标签: arrays bash sed grep cut

在我可以解释这个问题之前,我必须对此进行一些澄清。

我正在为dd-wrt路由器更改vpn脚本。请注意,此路由器没有bash,因此我通过entware进行了安装,例如sed grep cut之类的所有命令,等等。

现在,我的脚本调用另一个脚本并从中收集数据。 调用脚本的输出是

./nordvpn-server-find -l fr

Looking for servers located in FR with current capacity lower than 30%...

fr27.nordvpn.com     9%
fr104.nordvpn.com    10%
fr169.nordvpn.com    10%
fr25.nordvpn.com     10%
fr37.nordvpn.com     10%
fr80.nordvpn.com     11%
fr98.nordvpn.com     11%
fr114.nordvpn.com    12%
fr127.nordvpn.com    13%
fr16.nordvpn.com     13%
fr133.nordvpn.com    14%
fr41.nordvpn.com     14%
fr50.nordvpn.com     14%
fr62.nordvpn.com     14%
fr67.nordvpn.com     14%
fr19.nordvpn.com     15%
fr30.nordvpn.com     15%
fr31.nordvpn.com     15%
fr46.nordvpn.com     15%
fr84.nordvpn.com     15%

如您所见,这是当前负载的服务器列表,该列表的格式为列,因此在我的脚本中,我使用此命令仅使用该列表的前3个服务器

declare -a SERVERDIRS  # declare an array
SERVERDIRS+=($($COMMANDSPATH/bash $JFFSPATH/nordvpn-server-find -l it \
    | $COMMANDSPATH/head -6 | $COMMANDSPATH/tail -3 | $COMMANDSPATH/awk '{print $1}'))  

echo
echo ${SERVERDIRS[*]}  # echo all the elements of the array
echo "number of element in array" ${#SERVERDIRS[@]}
echo "first element in array" ${SERVERDIRS[0]}
echo "last element in array" ${SERVERDIRS[${#SERVERDIRS[@]}-1]}

请注意,$ COMMANDSPATH和$ JFFSPATH是指向正确位置的路径变量。如您所见,如果我没记错,我将第一个3台服务器放入一个数组中,然后可以对其进行操作,这里是有关数组创建的输出

#vpn rnd

fr27.nordvpn.com fr104.nordvpn.com fr169.nordvpn.com
number of element in array 3
first element in array fr27.nordvpn.com
last element in array fr169.nordvpn.com

现在一切看起来不错,数组是3个元素,依此类推

所以我的期望是提取第一个“。”之前的所有数据。然后将其格式化为4位数字 fr27.nordvpn.com->必须成为-> fr0027,依此类推。

所以我尝试了这种方法 https://repl.it/@jorman/JovialAngryWebpages 在repl.it上确实有效,但我不知道为什么,在bash上不行! 查看此解决方案的输出

    vpn rnd
    first var
    econd var 36
    1
    80
    third var

    irst var
    econd var 36
    1
    129
    third var

    irst var
    econd var 36
    1
    37
    third var

似乎有一个奇怪的错误,首先缺少char“ irst”,所以我在调试模式下运行它,请参阅日志

+ declare -a SERVERDIRS
+ SERVERDIRS+=($($COMMANDSPATH/bash $JFFSPATH/nordvpn-server-find -l fr | $COMMANDSPATH/head -6 | $COMMANDSPATH/tail -3 | $COMMANDSPATH/awk '{print $1}'))
++ /opt/bin/head -6
++ /opt/bin/bash /jffs//nordvpn-server-find -l fr
++ /opt/bin/tail -3
++ /opt/bin/awk '{print $1}'
+ for i in "${SERVERDIRS[@]}"
++ /opt/bin/sed 's/\..*//'
++ echo 'fr188.nordvpn.com'
++ /opt/bin/cut -c1-2
+ aaa='
pt/bin/sed 's/\..*//'
++ echo 'fr188.nordvpn.com'
++ /opt/bin/grep -oP '\d+'
+ bbb='36
1
188'
++ printf %04d 36 1 188
+ bbbmod=003600010188
+ ccc='
cho 'first var
irst var
cho 'second var 36
1
188'
second var 36
1
188
+ echo 'third var
hird var
cho

+ for i in "${SERVERDIRS[@]}"
++ echo 'fr193.nordvpn.com'
++ /opt/bin/cut -c1-2
++ /opt/bin/sed 's/\..*//'
+ aaa='
pt/bin/sed 's/\..*//'
++ /opt/bin/grep -oP '\d+'
++ echo 'fr193.nordvpn.com'
+ bbb='36
1
193'
++ printf %04d 36 1 193
+ bbbmod=003600010193
+ ccc='
cho 'first var
irst var
cho 'second var 36
1
193'
second var 36
1
193
+ echo 'third var
hird var
cho

+ for i in "${SERVERDIRS[@]}"
++ echo 'fr194.nordvpn.com'
++ /opt/bin/sed 's/\..*//'
++ /opt/bin/cut -c1-2
+ aaa='
cho 'fr194.nordvpn.com'
++ /opt/bin/grep -oP '\d+'
++ /opt/bin/sed 's/\..*//'
+ bbb='36
1
194'
++ printf %04d 36 1 194
+ bbbmod=003600010194
+ ccc='
cho 'first var
irst var
cho 'second var 36
1
194'
second var 36
1
194
+ echo 'third var
hird var
cho

+ echo

+ echo 'fr188.nordvpn.com' 'fr193.nordvpn.com' 'fr194.nordvpn.com'
fr188.nordvpn.com fr193.nordvpn.com fr194.nordvpn.com
+ echo 'number of element in array' 3
number of element in array 3
+ echo 'first element in array' 'fr188.nordvpn.com'
first element in array fr188.nordvpn.com
+ echo 'last element in array' 'fr194.nordvpn.com'
last element in array fr194.nordvpn.com
+ echo

+ echo 'fr188.nordvpn.com'
+ /opt/bin/sed 's/\..*//'
+ /opt/bin/sed 's/[^0-9]*//g'
361188
+ exit

如果您发现3、6和1似乎来自代码

++ /opt/bin/head -6
++ /opt/bin/bash /jffs//nordvpn-server-find -l fr
++ /opt/bin/tail -3
++ /opt/bin/awk '{print $1}'

我无法解释发生了什么事。

我想念一些代码吗?有一种更好的方法可以从数组中提取信息,我需要数组吗?

非常感谢能够阅读所有这些内容,并感谢所有会提出一些想法的人。

3 个答案:

答案 0 :(得分:0)

这可能有效(如果我正确理解了您想要实现的目标)。

echo "
Looking for servers located in FR with current capacity lower than 30%...

fr27.nordvpn.com     9%
fr104.nordvpn.com    10%
fr169.nordvpn.com    10%
fr25.nordvpn.com     10%
fr37.nordvpn.com     10%
fr80.nordvpn.com     11%
fr98.nordvpn.com     11%
fr114.nordvpn.com    12%
fr127.nordvpn.com    13%
fr16.nordvpn.com     13%
fr133.nordvpn.com    14%
fr41.nordvpn.com     14%
fr50.nordvpn.com     14%
fr62.nordvpn.com     14%
fr67.nordvpn.com     14%
fr19.nordvpn.com     15%
fr30.nordvpn.com     15%
fr31.nordvpn.com     15%
fr46.nordvpn.com     15%
fr84.nordvpn.com     15%
" | awk 'BEGIN { counter=0; } /nordvpn.com/ { split($1, a, /\./); print a[1]; counter++; if ( counter == 3 ) exit; }'
fr27
fr104
fr169

很明显,在您的情况下,您不应使用echo,而应直接使用脚本的输出。

答案 1 :(得分:0)

您的问题尚不清楚,因此让我们从清理您的Shell脚本开始,看看我们要去哪里。鉴于此输入:

$ cat file

Looking for servers located in FR with current capacity lower than 30%...

fr27.nordvpn.com     9%
fr104.nordvpn.com    10%
fr169.nordvpn.com    10%
fr25.nordvpn.com     10%
fr37.nordvpn.com     10%
fr80.nordvpn.com     11%
fr98.nordvpn.com     11%
fr114.nordvpn.com    12%
fr127.nordvpn.com    13%
fr16.nordvpn.com     13%
fr133.nordvpn.com    14%
fr41.nordvpn.com     14%
fr50.nordvpn.com     14%
fr62.nordvpn.com     14%
fr67.nordvpn.com     14%
fr19.nordvpn.com     15%
fr30.nordvpn.com     15%
fr31.nordvpn.com     15%
fr46.nordvpn.com     15%
fr84.nordvpn.com     15%

然后执行当前正在执行的脚本操作,应这样写:

$ cat tst.sh
serverDirs=( $(
        cat file |
        awk 'NR>3{print $1} NR==6{exit}'
) )

printf '\n'
printf '%s\n' "${serverDirs[*]}"         # print all the elements of the array
printf 'number of element in array %s\n' "${#serverDirs[@]}"
printf 'first element in array %s\n'     "${serverDirs[0]}"
printf 'last element in array %s\n'      "${serverDirs[${#serverDirs[@]}-1]}"
$
$ ./tst.sh

fr27.nordvpn.com fr104.nordvpn.com fr169.nordvpn.com
number of element in array 3
first element in array fr27.nordvpn.com
last element in array fr169.nordvpn.com

很明显,我用cat file代替了$COMMANDSPATH/bash $JFFSPATH/nordvpn-server-find -l it,因为我将其余脚本的输入保存在file中,而我没有nordvpn-server-find而且我没有为awk命令加上$COMMANDSPATH/前缀,因为我没有设置该变量。

除此之外-使用awk时不需要头+尾加管道,不要为非导出变量名使用所有大写字母,以免与导出变量冲突,printf比echo更可移植,并且除非您有特定目的,否则必须始终引用Shell变量。所以,我已经照顾了所有这些。

现在,您还需要什么?我没有在您的问题中看到预期的输出,而我所看到的暗示预期的输出可能是So my expectation is to extract all the data before the very first "." and then format it to have it with 4 digits, for example fr27.nordvpn.com -> have to became -> fr0027 and so on.-如果仅此而已,那么我们只需更改awk脚本即可:

$ cat tst.sh
serverDirs=( $(
        cat file |
        awk '
            NR>3 {
                alpha = num = rest = $1
                sub(/[0-9].*/,"",alpha)
                gsub(/^[^0-9]+|\..*/,"",num)
                sub(/^[^.]+/,"",rest)
                num = sprintf("%04d",num)
                print alpha num rest
            }
            NR==6 { exit }
        '
) )

printf '\n'
printf '%s\n' "${serverDirs[*]}"         # print all the elements of the array
printf 'number of element in array %s\n' "${#serverDirs[@]}"
printf 'first element in array %s\n'     "${serverDirs[0]}"
printf 'last element in array %s\n'      "${serverDirs[${#serverDirs[@]}-1]}"
$
$ ./tst.sh

fr0027.nordvpn.com fr0104.nordvpn.com fr0169.nordvpn.com
number of element in array 3
first element in array fr0027.nordvpn.com
last element in array fr0169.nordvpn.com

那是你想做什么?

答案 2 :(得分:0)

首先,我想让所有对此做出回应的人加入坦克! 我读了一些好的代码,将在这个小脚本中实现。

但是我发现了问题: 查看日志和调试,我看到这样的代码

[\033

在我的脑海中,我确定自己已经看过了!

返回服务器的nordvpn脚本加载,并用tput写入输出,因此输出是彩色的!碰巧所有这些信息都跳入了代码中,并且当所有逻辑切掉grep并解析所有信息时,“颜色代码”仍然存在并且有所作为!

所以我禁用了彩色输出,所有的工作都像是一个吊饰!

许多战车为您提供时间和帮助,就像往常一样