通过行和列的变量进行Bash循环

时间:2017-06-23 12:57:52

标签: bash shell

在搜索了不同解决方案的数小时后,我还没有找到一个可行的解决方案。 Bash和Shell Scripting不是我最强的领域。

我有一个变量,它有行(新行)和列(制表符分隔)。我想要做的是循环遍历行并获取'列X'然后将该项放入变量中,以便我可以对该单元格执行某些操作。即例如回声。

行数未知,但已知列数,因此可以始终以列3为例。

我在Linux上运行Bash v.4。

示例输入(无法在这里找到实际'标签'事物的方法吗?);

UniqueID1 -tab- Description -tab- FriendlyNameABC
UniqueID1 -tab- Description -tab- FriendlyNameXYZ

示例输出将循环遍历列表,获取FriendlyNameABC(col 3)并将其回显。

我正在尝试在此处展开​​此脚本,https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=77277&p=1178478#p1178478 - 这是一个通过WPS连接到WiFi的shell脚本。该页面上提供的脚本(下面仅供参考)有效,但它依赖于仅选择最强的WiFi信号,这并不总是您要连接的网络。

#!/bin/bash
# only run if there's no current wifi connection
if  ! ifconfig wlan0 | grep -q "inet addr:" ; then
       # grab AP's that support WPS, sort by strength and select the strongest 
        wpa_cli scan_results | grep WPS | sort -r -k3 | awk 'END{print $NF}'  >/tmp/wifi
        read ssid < /tmp/wifi
        wpa_cli wps-pbc $ssid
fi

目前,我已设法修改上面的脚本,以便以'wpa_cli ..'开头的行现在读取如下,这将整个标识的WiFi网络放在一个变量中,但后来我很难分裂全力以赴。

wpa_cli scan_results | grep WPS | sort -r -k3 $allConnections

本质上,上面的代码我需要翻译成这个伪代码;

#!/bin/bash
# only run if there's no current wifi connection
if  ! ifconfig wlan0 | grep -q "inet addr:" ; then
       # grab AP's that support WPS, sort by strength and select the strongest 
        wpa_cli scan_results | grep WPS | sort -r -k3 | awk 'END{print $NF}'  >/tmp/wifi
        read ssid < /tmp/wifi

        #This is the section below that I'm struggling to implement (this is pseudo code, the only bit of working code is the line starting with wpa_cli...)
        while(ssid.hasNext(){
            #Try connecting to the network
            wpa_cli wps-pbc $ssid
            if(successful){break();}
        }
fi

我应该补充一下,我假设数据是制表符,并根据我运行命令时布局的外观划分新行;

wpa_cli scan_results

在Linux命令行运行命令时,有没有办法确认分隔符?

3 个答案:

答案 0 :(得分:1)

如果您的“每个单元格”逻辑足够简单,您可以执行以下操作:

echo $VARIABLE | cut -f3 -d$'\t' | xargs echo

# echo $VARIABLE |       # pipe the value of VARIABLE to the next statement...
# cut -f3 -d$'\t' |      # take the 3rd column, using tabs for the delimiters
# xargs echo             # for each resulting row, call `echo` with that row as the argument

如果你需要做一些更复杂的事情:

for CELL in $(echo $VARIABLE | cut -f3 -d$'\t'); do     # for each line in the result of this command...
    echo $CELL
    # Other stuff with $CELL
done

答案 1 :(得分:0)

简单永远胜利。我设法解决了这个问题。人们评论的帮助,谢谢,这有助于我在测试各种脚本时澄清一些事情。

在对所有内容进行测试后,显而易见的是数据被破坏的方式并不完全正确。空格被视为选项卡,这意味着您要连接的SSID网络名称,当它应该是“我的网络”时,它将简称为“网络”,然后由于没有网络称为“网络”网络”。因此,在删除几乎所有代码并简化操作之后,我记得以前测试过你实际上并不需要提供网络名称,你可以简单地运行命令而不需要任何更智能的逻辑,这简化了一切。

#!/bin/bash
# only run if there's no current wifi connection
if  ! ifconfig wlan0 | grep -q "inet addr:" ; then
        wpa_cli wps-pbc
fi

您将在上面注意到,此脚本只是监听正在按下的WPS按钮并自动连接到该网络。无论这是最强的信号,还是天气,这个网络名称都有空格。

答案 2 :(得分:0)

首先花一点时间考虑echo $aecho "$a"之间的区别 在第一种情况下,a的值作为单独的字段赋予echo,在第二种情况下作为1字段。因此,在第一种情况下bash将更改标签和换行符,删除可能位于$a中的所有行和列。
a填充为4行的一种棘手方法是在格式化字符串中提供printf个更多参数:

a=$(printf "%s\t%s\t%s\n" 1 a A 2 b B 3 c C 4 "F o u r" "4 4 4 4" )

printf之后,echo可能会让您大吃一惊:

you> echo $a | sed -r 's/\t/<tab>/g'
1 a A 2 b B 3 c C 4 F o u r 4 4 4 4
you> echo "$a" | sed -r 's/\t/<tab>/g'
1<tab>a<tab>A
2<tab>b<tab>B
3<tab>c<tab>C
4<tab>F o u r<tab>4 4 4 4

您可以从a的calue创建一个循环,将每个字段分配给另一个变量,此示例切换字段:

you> while IFS=$'\t' read -r id desc friend; do
   echo "$id = ${friend} (${desc})"
done <<< "$a"
1 = A (a)
2 = B (b)
3 = C (c)
4 = 4 4 4 4 (F o u r)

我不懂行

wpa_cli scan_results | grep WPS | sort -r -k3 $allConnections

如果要对grep结果进行排序,则应删除$allConnections(或为空)。当var allConnections填充文件名时,您可以使用> $allConnections(重定向到文件),但我认为您希望将结果存储在var中。     allConnections = $(wpa_cli scan_results | grep WPS | sort -r -k3) 现在你可以做类似

的事情了
while IFS=$'\t' read -r id desc friend; do
    echo "Trying ssid ${id} = ${friend} (${desc})"
    wpa_cli wps-pbc ${id} && break
done <<< "$allConnections"

&& break假设wpa_cli成功时返回0。