シェルスクリプトでは、コマンドが正しく機能しません。

シェルスクリプトでは、コマンドが正しく機能しません。

出力は次のとおりです。

sudo iwlist scan 2>/dev/null | grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null 
ヤシシャ
コアピース
CoreFragment_5G
コアピース
デリアン
ヤシシャ
コンパスト
アプリバズ_技術
共生
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
コアピース
ヤッシュ
シャ
赤い翼
実嫌悪
コンパスト
アプリバズ_技術
共生
CoreFragment_5G
赤い翼
LABS_5G

ノート: 出力に空白がある場合は、新しい行として扱われます。

Ubuntu 18.04を使用しています。

答え1

まず、そうではないことに注意してください。一つコマンドは異なる動作をします。コードフラグメントでは、標準出力は2つの完全に異なるコマンドで書かれています。
最初の印刷物の出力sedと2番目の印刷物の出力は次のとおりです。

  1. の出力がsed置き換えられます(コマンド置換を介して$(...)in
  2. 結果の文字列は要素のリストに展開されます。
  3. 各項目は順番にに割り当てssid_nameられ、印刷されますecho

ポイント2の拡張は、内部フィールド区切り記号()の値に基づいており、IFSデフォルト値はです<space><tab><newline>。したがって、あなたのソリューションforこれは、置き換えられた文字列を改行に分割することのみを許可するために機能します。

あなたの答えとは別に、多くのシェルがその構文()をサポートしていても$'\n'移植性がないことに注意してください。ただし、次の割り当てを使用できます。$'string'

IFS='
'

入力行を処理するもう1つの構成は、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ループを使用することをお勧めします。readfor

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'

関連情報