Befehl funktioniert im Shell-Skript nicht richtig

Befehl funktioniert im Shell-Skript nicht richtig

Hier ist die Ausgabe von:

sudo iwlist scan 2>/dev/null | grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null 
Yash Shah
Kernfragment
KernFragment_5G
Kernfragment
dlink
Yash Shah
COMFAST
Appbirds_Technologies
SYMBIOSE
20096641
KernFragment_5G
AMBER_AP1
REDWING LABS_5G

Wenn man dasselbe in ein Skript schreibt, funktioniert es nicht immer gleich.

Hier ist ein Snippet, in dem ich den obigen Befehl verwendet habe.

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

Ich habe folgende Ausgabe erhalten:

Yash
Schah
Kernfragment
KernFragment_5G
Kernfragment
Yash
Schah
ROTER FLÜGEL
LABORE
COMFAST
Appbirds_Technologies
SYMBIOSE
KernFragment_5G
ROTER FLÜGEL
LABS_5G

Notiz: Wenn die Ausgabe ein Leerzeichen enthält, wird es als neue Zeile verwendet.

Ich arbeite an Ubuntu 18.04.

Antwort1

Beachten Sie zunächst, dass es nichteinsBefehl verhält sich anders. In Ihren Codeausschnitten wird die Standardausgabe von zwei ganz unterschiedlichen Befehlen geschrieben.
Ihr erster druckt seddie Ausgabe von , während Ihr zweiter:

  1. Die Ausgabe von wird (durch den Befehl substitution ) nach sedersetzt ;$(...)in
  2. Die resultierende Zeichenfolge wird in eine Liste von Elementen erweitert.
  3. Jeder Artikel wird wiederum zugewiesen ssid_nameund von diesem gedruckt echo.

Die Erweiterung in Punkt 2 erfolgt gemäß dem Wert des internen Feldtrennzeichens ( IFS), der standardmäßig ist <space><tab><newline>. SomitIhre Lösungfunktioniert, weil es fordie Aufteilung der ersetzten Zeichenfolge nur bei Zeilenumbrüchen zulässt.

Beachten Sie neben Ihrer Antwort, dass dies $'\n'nicht portierbar ist – auch wenn diese Syntax ( $'string') in vielen Shells unterstützt wird.
Sie können dennoch eine Zuweisung wie diese verwenden:

IFS='
'

Eine alternative Konstruktion zum Verarbeiten von Eingabezeilen ist die Verwendung readin einer whileSchleife:

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

Auch hier sedwird jede Zeile der Ausgabe entsprechend dem Wert von aufgeteilt IFS– der in diesem Beispiel genau auf die Nullzeichenfolge gesetzt wird, um jegliche Auswirkungen einer Wortaufteilung zu verhindern – die Zeilen würden jedoch readunabhängig von durch getrennt bleiben IFS.

Antwort2

Verwenden Sie besser eine whileSchleife mit readanstelle einer forSchleife.

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

siehe auchhttps://mywiki.wooledge.org/BashFAQ/001

Antwort3

Durch Hinzufügen der folgenden Zeile im Code vor der For-Schleife funktionierte es in meinem Fall einwandfrei.

IFS=$'\n'

verwandte Informationen