命令在 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'

相關內容