命令在 shell 脚本中无法正常工作

命令在 shell 脚本中无法正常工作

这是输出:

sudo iwlist scan 2>/dev/null | grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null 
亚什·沙阿
核心片段
CoreFragment_5G
核心片段
德联
亚什·沙阿
康法斯特
Appbirds_技术
共生
20096641
CoreFragment_5G
琥珀_AP1
红翼实验室_5G

虽然在脚本中编写的相同内容的工作方式并不相同。

这是我使用上面命令的一个片段。

for ssid_name in $(sudo iwlist scan 2>/dev/null | grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null)
do
    echo "$ssid_name"
done

我得到这样的输出:

亚什
沙阿
核心片段
CoreFragment_5G
核心片段
亚什
沙阿
红翼
实验室
康法斯特
Appbirds_技术
共生
CoreFragment_5G
红翼
LABS_5G

笔记:当输出中有空格时,将作为新行。

我正在使用 Ubuntu 18.04。

答案1

首先请注意,它不是命令的行为不同。在您的代码片段中,标准输出是由两个完全不同的命令编写的。
您的第一个打印sed的输出,而在第二个打印中:

  1. 的输出sed被替换(通过命令替换$(...)in
  2. 结果字符串被扩展为元素列表;
  3. 每个项目依次分配给ssid_name并由 打印echo

第 2 点的扩展是根据内部字段分隔符 ( ) 的值进行的IFS,默认为<space><tab><newline>。因此,你的解决方案之所以有效,是因为它只允许for在换行符上分割替换的字符串。

作为您答案的旁白,请注意,它$'\n'不可移植 - 即使$'string'许多 shell 都支持该语法 ( )。
不过,您可以使用这样的分配:

IFS='
'

处理输入行的另一种构造是在循环read中使用while

sudo iwlist scan 2>/dev/null | grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null |
while IFS= read -r i; do
    printf '%s\n' "$i"
done

在这里,sed的输出的每一行也根据 的值进行分割IFS- 在本例中设置为空字符串,以防止任何单词分割的影响 - 但行将保持由read分隔IFS

答案2

最好使用while循环read而不是for循环。

sudo iwlist scan 2>/dev/null |grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null | while IFS= read -r ssid_name
do
    echo $ssid_name
done

也可以看看https://mywiki.wooledge.org/BashFAQ/001

答案3

通过在 for 循环之前在代码中添加以下行,在我的情况下可以正常工作。

IFS=$'\n'

相关内容