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

Yas*_*hah 3 shell-script

这是输出:

sudo iwlist scan 2>/dev/null | grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null 
Run Code Online (Sandbox Code Playgroud)
亚什沙
核心片段
CoreFragment_5G
核心片段
链接
亚什沙
康快
应用鸟_科技
共生
20096641
CoreFragment_5G
AMBER_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
Run Code Online (Sandbox Code Playgroud)

我得到这样的输出:

亚什
沙阿
核心片段
CoreFragment_5G
核心片段
亚什
沙阿
红翼
实验室
康快
应用鸟_科技
共生
CoreFragment_5G
红翼
LABS_5G

注意:当输出中有空格时,它将作为一个新行。

我正在使用 Ubuntu 18.04。

fra*_*san 8

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

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

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

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

IFS='
'
Run Code Online (Sandbox Code Playgroud)

处理输入行的另一种构造是readwhile循环中使用:

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
Run Code Online (Sandbox Code Playgroud)

在这里, 的每一行sed的输出也根据 的值进行拆分IFS——在这个例子中,它被精确地设置为空字符串以防止分词的任何影响——但行将保持分隔,read而不管IFS.