2016-03-28 13 views
2

Ich habe dieses Beispiel-Code:Vermeiden Subshell aus Rohr auf Schlag

find "$1" ! -regex "$regex" 2>/dev/null | while read line ; do 
    a="$line" 
done 

echo ("$a") # prints nothing because of subshell 

ich brauche:

  • Abhilfe für Subshell $a sichtbar außerhalb zu machen (in global scope)
  • nicht verwenden bash's process substitution
  • Kompatibel mit Dash, Bash und Korn Shell

Wie kann ich das erreichen? Gibt es eine einfache Lösung?

Antwort

1

Verwenden Sie eine explizit benannte Pipe.

mkfifo named_pipe 
find "$1" ! -regex "$regex" 2> /dev/null > named_pipe & 

while read line; do 
    a=$line 
done < named_pipe 
+0

Gibt es eine Möglichkeit, die Erstellung von Dateien zu vermeiden? Wir können keine temporären Dateien machen: S –

+1

Angst nicht. Ihre einzige andere Möglichkeit besteht darin, den Aufruf von 'find' durch eine Shell-Funktion zu ersetzen (rekursiv, wenn Sie in Unterverzeichnisse absteigen müssen), die eine 'for'-Schleife verwendet, um alle Dateien in der aktuellen Verzeichnishierarchie zu durchlaufen. 'expr' kann verwendet werden, um jede Datei gegen den regulären Ausdruck zu prüfen, oder Sie können vielleicht mit einem Dateinamenmuster davonkommen, wenn die Regex nicht zu kompliziert ist. – chepner

+0

Okay, naja, es funktioniert trotzdem einwandfrei, also Markierung als gelöst. Danke vielmals! :) –

4

Wenn ich Sie richtig verstanden habe, ist es nicht so sehr die Subshell, die Sie stört, aber die Tatsache, dass die Variable ihren Wert nicht außerhalb des Subshell nicht behält. Sie könnten Code verwenden, wie diese Gruppierung:

find "$1" ! -regex "$regex" 2>/dev/null | 
{ 
    while read line 
    do 
    a=$line 
    done 
    echo "$a" 
} 

Sie den Wert der Variablen a verwenden kann, solange es innerhalb der geschweiften Klammern ist.

0

Ohne eine Named Pipe und ohne in einer Subshell das Ganze läuft, können Sie eine here-doc mit einem command substitution innerhalb des hier-doc verwenden:

while read line; do 
    a=$line 
done <<EOF 
    $(find "$1" ! -regex "$regex" 2>/dev/null) 
EOF 

echo "$a" 

Dieses tragbare sein sollte.

Siehe auch.BashFAQ/024.

Hinweis. Parsing die Ausgabe von find wie folgt ist ein Antipattern.